From 1d304511b8a4cd520926348bf10fc34c4490f7c3 Mon Sep 17 00:00:00 2001 From: Zack Meier Date: Wed, 15 Apr 2026 15:45:50 -0500 Subject: [PATCH] update --- _NDGOV_CS/ITD.Cohesity/.gitignore | 4 + _NDGOV_CS/ITD.Cohesity/README.md | 110 + .../AddRemoveVMTagIdsToProtectionGroup.ps1 | 98 + .../archive/powershell/ITD.Cohesity.nuspec | 9 + .../archive/powershell/ITD.Cohesity.psd1 | 10 + .../archive/powershell/ITD.Cohesity.psm1 | 116 + .../ITD.Cohesity/archive/powershell/README.md | 31 + .../powershell/Windows-ServiceRunAs.ps1 | 27 + .../powershell/addObjectToUserAccessList.ps1 | 120 + .../archive/powershell/cohesity-api.ps1 | 813 + _NDGOV_CS/ITD.Cohesity/azure-pipelines.yml | 32 + .../beta/getSQLSourceErrorMessages.py | 109 + _NDGOV_CS/ITD.Cohesity/beta/regexTest.py | 30 + _NDGOV_CS/ITD.Cohesity/beta/systemHealth.py | 62 + .../beta/temp-fixProtectionJobAttributes.py | 372 + _NDGOV_CS/ITD.Cohesity/beta/template.py | 89 + .../beta/updateSQLProtectionJob_policy.py | 21 + _NDGOV_CS/ITD.Cohesity/cancelJobs.py | 57 + .../ITD.Cohesity/classes/automationsAPI.py | 7 + _NDGOV_CS/ITD.Cohesity/classes/cohesityAPI.py | 792 + _NDGOV_CS/ITD.Cohesity/classes/itdSnow.py | 502 + .../ITD.Cohesity/classes/serviceNowAPI.py | 502 + .../ITD.Cohesity/classes/sharePointAPI.py | 175 + _NDGOV_CS/ITD.Cohesity/dailyBackupReview.py | 770 + _NDGOV_CS/ITD.Cohesity/dailyErrors.py | 217 + .../ITD.Cohesity/dailyProtectionReview.py | 646 + _NDGOV_CS/ITD.Cohesity/diskAlerts.py | 124 + _NDGOV_CS/ITD.Cohesity/findDuplicates.py | 55 + _NDGOV_CS/ITD.Cohesity/pauseOrResumeJob.py | 96 + _NDGOV_CS/ITD.Cohesity/reNameJobs.py | 130 + _NDGOV_CS/ITD.Cohesity/registerServer.py | 118 + _NDGOV_CS/ITD.Cohesity/requirements.txt | 86 + .../ITD.Cohesity/sqlServerRegistration.py | 196 + _NDGOV_CS/ITD.Cohesity/template.py | 55 + _NDGOV_CS/ITD.Cohesity/unRegisterServer.py | 93 + _NDGOV_CS/ITD.Cohesity/updateAzPolicy.py | 107 + .../ITD.Cohesity/updateAzProtectionJobs.py | 196 + .../ITD.Cohesity/updateIndexingPolicy.py | 118 + .../ITD.Cohesity/updateProtectionGroupTags.py | 268 + _NDGOV_CS/ITD.Cohesity/vars/exemptions.yml | 171 + .../verified/validate_replication.py | 126 + _NDGOV_CS/ITDAzureRM/ITDAzureRM.psd1 | 139 + _NDGOV_CS/ITDAzureRM/ITDAzureRM.psm1 | 1437 + _NDGOV_CS/ITDAzureRM/NewVMExistingDisk.ps1 | 102 + _NDGOV_CS/ZM1/README.md | 20 + _NDGOV_CS/ZM1/first-playbook.yml | 12 + _NDGOV_CS/cecogdill/snowSample.zip | Bin 0 -> 6086 bytes .../ITD.All-General/Build/azure-pipelines.yml | 49 + .../ITD.All-General/Build/build.ps1 | 17 + .../ITD.All-General/ITD.All-General.nuspec | 12 + .../ITD.All-General/ITD.All-General.psd1 | 11 + .../ITD.All-General/ITD.All-General.psm1 | 23 + .../Public/ConvertTo-Array.ps1 | 32 + .../Public/Get-SslCertificate.ps1 | 43 + .../Public/Test-ADCredential.ps1 | 49 + .../Public/Uninstall-ITDModuleOldVersion.ps1 | 50 + .../Public/Update-ITDModule.ps1 | 33 + _NDGOV_WindowsTeam/ITD.All-General/README.md | 20 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../Helpers/^template.json | 21 + .../Helpers/itddohslimst2.nd.gov.json | 26 + .../Helpers/itdernappt01.nd.gov.json | 14 + .../Helpers/itdernappu01.nd.gov.json | 14 + .../Helpers/itdscmt1.nd.gov.json | 20 + .../Helpers/itdvmvc1script.nd.gov.json | 14 + .../Helpers/itdwinautot1.nd.gov.json | 14 + ...TD.ITD-WindowsServer.FileManagement.nuspec | 12 + .../ITD.ITD-WindowsServer.FileManagement.psd1 | 132 + .../ITD.ITD-WindowsServer.FileManagement.psm1 | 23 + .../Private/ITDExpiredFiles.json | 26 + .../Private/ITDExpiredFiles.yml | 22 + .../Private/ITDExpiredFilesSource.jsonbak | 14 + .../Public/Get-ITDExpiredFiles.ps1 | 89 + .../Public/Remove-ITDExpiredFiles.ps1 | 99 + .../README.md | 20 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../old_needs_review/New-ITDWindowsVm.ps1 | 93 + .../New-ITDWindowsVmAzure.ps1 | 694 + .../New-ITDWindowsVmVMware.ps1 | 1037 + .../ITD.ITD-WindowsServer.General.nuspec | 12 + .../ITD.ITD-WindowsServer.General.psd1 | 132 + .../ITD.ITD-WindowsServer.General.psm1 | 23 + .../New-ITDSSLCertificateSigningRequest.ps1 | 154 + .../New-ITDSSLCertificateSigningRequest.ps1 | 154 + .../Public/Remove-ITDSolarwindsNode.ps1 | 34 + .../ITD.ITD-WindowsServer.General/README.md | 20 + .../Scripts/DomainJoin_example.ps1 | 19 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../ITD.ITD-WindowsServer.Lifecycle.nuspec | 12 + .../ITD.ITD-WindowsServer.Lifecycle.psd1 | 132 + .../ITD.ITD-WindowsServer.Lifecycle.psm1 | 23 + .../Public/New-ITDWindowsVmAzureStep1.ps1 | 447 + .../Public/New-ITDWindowsVmAzureStep2.ps1 | 341 + .../Public/New-ITDWindowsVmVMwareStep1.ps1 | 529 + .../Public/New-ITDWindowsVmVMwareStep2.ps1 | 667 + .../Public/Remove-ITDWindowsServer.ps1 | 290 + .../Scripts/DomainJoin_example.ps1 | 19 + .../Scripts/PSU_errorchecking.ps1 | 29 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../ITD.Infra-ActiveDirectory.Object.nuspec | 12 + .../ITD.Infra-ActiveDirectory.Object.psd1 | 132 + .../ITD.Infra-ActiveDirectory.Object.psm1 | 23 + .../Public/Disable-ITDADUser.ps1 | 49 + .../Public/Get-ITDADActiveServer.ps1 | 27 + .../Public/Get-ITDADGroupMember.ps1 | 30 + .../Public/New-ITDADComputerServer.ps1 | 68 + .../Public/New-ITDADGroup.ps1 | 93 + .../Public/New-ITDADServiceAccount.ps1 | 123 + .../Public/New-ITDADServiceAccountOLD.ps1 | 118 + .../Public/New-ITDADServiceAccountRitm.ps1 | 88 + .../Public/Unlock-ITDADAccount.ps1 | 80 + .../README.md | 20 + ...w-ITDADServiceAccountFromSCTask_script.ps1 | 147 + .../New-ITDADServiceAccountRITM_script.ps1 | 40 + .../New-ITDADServiceAccount_script.ps1 | 78 + .../UD_PSU/NewITDADServiceAccountRequest.ps1 | 49 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../Data/Config.json | 14 + ....Infra-Certificate-External.Sectigo.nuspec | 12 + ...TD.Infra-Certificate-External.Sectigo.psd1 | 132 + ...TD.Infra-Certificate-External.Sectigo.psm1 | 25 + .../Private/Set-OnLoad.ps1 | 37 + .../Public/Download-SectigoCertificate.ps1 | 71 + .../Enroll-SectigoCertificateRequest.ps1 | 149 + .../Public/Get-SectigoApiToken.ps1 | 46 + .../Public/Get-SectigoCertificate.ps1 | 37 + .../Public/Get-SectigoCertificateTypes.ps1 | 42 + .../Public/Get-SectigoOrg.ps1 | 44 + .../Public/Get-SectigoSeverTypes.ps1 | 43 + .../Public/Revoke-SectigoCertificate.ps1 | 46 + .../Public/Test-SectigoCertificateRequest.ps1 | 39 + .../README.md | 122 + .../certmgr-api-doc-25.8.html | 41951 +++++++++++++++ .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../ITD.Infra-Networking-Infoblox.nuspec | 12 + .../ITD.Infra-Networking-Infoblox.psd1 | 10 + .../ITD.Infra-Networking-Infoblox.psm1 | 337 + .../ITD.Infra-Networking-Infoblox/README.md | 20 + .../Build/azure-pipelines.yml | 49 + .../ITD.Infra-Passwordstate/Build/build.ps1 | 17 + .../ITD.Infra-Passwordstate.nuspec | 12 + .../ITD.Infra-Passwordstate.psd1 | 10 + .../ITD.Infra-Passwordstate.psm1 | 23 + .../Public/Export-ITDPasswordList.ps1 | 52 + .../Public/Find-ITDPassword.ps1 | 49 + .../Public/Get-ITDPassword.ps1 | 99 + .../Public/Get-ITDPasswordAccountTypeId.ps1 | 35 + .../Public/Get-ITDPasswordList.ps1 | 58 + .../Public/New-ITDPassword.ps1 | 134 + .../Public/New-ITDRandomPassword.ps1 | 52 + .../Public/Remove-ITDPassword.ps1 | 95 + .../Public/Update-ITDPassword.ps1 | 116 + .../ITD.Infra-Passwordstate/README.md | 20 + .../.universal/Get-ITDServiceNowRecord | 7 + .../.universal/accessControls.ps1 | 17 + .../.universal/authentication.ps1 | 87 + .../.universal/dashboards.ps1 | 6 + .../.universal/endpoints.ps1 | 1 + .../.universal/loginPage.ps1 | 15 + .../.universal/publishedFolders.ps1 | 1 + .../.universal/roles.ps1 | 149 + .../.universal/schedules.ps1 | 27 + .../.universal/scripts.ps1 | 56 + .../.universal/settings.ps1 | 6 + .../.universal/tags.ps1 | 21 + .../.universal/variables.ps1 | 16 + .../Get-ITDExpiredFiles.ps1 | 13 + .../Remove-ITDExpiredFiles_Auto.ps1 | 119 + .../Approve-ITDWindowsServer.ps1 | 146 + .../New-ITDWindowsVmAzure_Manual.ps1 | 130 + .../New-ITDWindowsVmVMware_Manual.ps1 | 118 + .../New-ITDWindowsVmAzure_Step1.ps1 | 176 + .../New-ITDWindowsVmAzure_Step1.ps1.orig | 151 + .../New-ITDWindowsVmAzure_Step2.ps1 | 75 + .../New-ITDWindowsVmVMware_Step1.ps1 | 157 + .../New-ITDWindowsVmVMware_Step2.ps1 | 87 + .../New-ITDWindowsVm_Auto.ps1 | 146 + .../New-ITDWindowsVm_Step3.ps1 | 126 + .../Remove-ITDWindowsServer.ps1 | 92 + .../Add-ITDADUserSPN.ps1 | 96 + .../Deploy-Client.ps1 | 1 + .../New-ITDADServiceAccount.ps1 | 134 + .../Get-RegistrationList .ps1 | 3 + .../Invoke-CertAutoRenew.ps1 | 60 + .../Invoke-CertificateDeploy.ps1 | 61 + .../New-ITDCertificateRequestSectigo.ps1 | 489 + .../New-SectigoPfxCertificate.ps1 | 426 + .../Register-CommonName.ps1 | 168 + .../Troubleshooting.ps1 | 17 + .../Unregister-CommonName.ps1 | 27 + .../Update-Client.ps1 | 17 + .../Add-ITDSolarwindsNode.ps1 | 31 + .../Remove-ITDSolarwindsNode.ps1 | 10 + .../Update-ITDSolarwindsNodeFromSNowRitm.ps1 | 38 + .../New-ITDPSUScript.ps1 | 36 + .../Update-ITDModule.ps1 | 42 + .../Get-ITDVMwareLunIdNextAvailable.ps1 | 1 + .../Get-ITDVMwareVMGuestIPsForPA.ps1 | 131 + .../Sync-ITDOneViewServerInventoryToSql.ps1 | 270 + .../Sync-ITDVMwareClusterMetadataToSql.ps1 | 192 + .../Sync-ITDVMwareHostMetadataToSql.ps1 | 216 + .../Sync-ITDVMwareVMMetadataToSql.ps1 | 300 + .../Update-ITDVMwareILOSslCertificate.ps1 | 247 + .../New-ITDVMwareVMSnapshotTask.ps1 | 133 + .../Remove-ITDVMwareVMSnapshotExpired.ps1 | 99 + .../Update-ITDVMwareVMSnapshotStatus.ps1 | 203 + .../Add-ITDServerBuildRitmToSql.ps1 | 90 + .../Move-ITDVMwareVMToAppNameFolder_Auto.ps1 | 46 + .../Set-ITDVMwareVMTagFromCmdb.ps1 | 58 + .../Sync-ITDServerBuildRITMs.ps1 | 158 + .../Sync-ITDVMwareVMMetadataToSharePoint.ps1 | 25 + .../Sync-ITDVMwareVMTagsFromCmdb.ps1 | 10 + .../Update-ITDSnowVMTaskDescription.ps1 | 2 + .../ZM-Test/Get-HelloWorld.ps1 | 21 + .../ZM-Test/New-TestNestedInvoke.ps1 | 152 + .../ZM-Test/Test-AzIaaSCredential.ps1 | 6 + .../ZM-Test/Test-ITDSchedule.ps1 | 77 + .../ZM-Test/Test-ITDScheduleWithCreds.ps1 | 11 + .../ZM-Test/Test-InvokeZM.ps1 | 5 + .../ZM-Test/Test-PSUVariable.ps1 | 2 + .../ZM-Test/Test-ZMFile.ps1 | 16 + .../ZM-Test/Test-ZMVariable.ps1 | 16 + .../ZM-Test/test-sql.ps1 | 18 + .../ITD-WindowsServer_FileManagement.ps1 | 25 + .../pages/PRD.ps1 | 30 + .../pages/home.ps1 | 3 + .../Infra-VMware_Snapshot.ps1 | 30 + .../Infra-VMware_Snapshot/pages/PRD.ps1 | 57 + .../Infra-VMware_Snapshot/pages/home.ps1 | 3 + .../NewITDADServiceAccount.ps1 | 13 + .../pages/ADServiceAccount.ps1 | 34 + .../NewITDADServiceAccount/pages/home.ps1 | 3 + .../PSUVariableReview/PSUVariableReview.ps1 | 17 + .../PSUVariableReview/pages/Users.ps1 | 26 + .../PSUVariableReview/pages/home.ps1 | 3 + .../RemoveITDExpiredFiles.ps1 | 3 + .../RemoveITDExpiredFiles/pages/home.ps1 | 3 + .../dashboards/ServiceNow/ServiceNow.ps1 | 33 + .../ServiceNow/pages/AppNameLookup.ps1 | 58 + .../ServiceNow/pages/ApplicationServerV2.ps1 | 25 + .../ServiceNow/pages/AzureVmSizeHelper.ps1 | 23 + .../ServiceNow/pages/CMDBServerList.ps1 | 154 + .../dashboards/ServiceNow/pages/CiLookup.ps1 | 97 + .../dashboards/ServiceNow/pages/CiTest.ps1 | 4 + .../ServiceNow/pages/ServerBuildRequestV1.ps1 | 39 + .../dashboards/ServiceNow/pages/home.ps1 | 11 + .../ServiceNowDumps/ServiceNowDumps.ps1 | 21 + .../pages/ApplicationServerV2.ps1 | 25 + .../pages/ServerBuildRequestV1.ps1 | 42 + .../dashboards/ServiceNowDumps/pages/home.ps1 | 3 + .../UniversalAutomation/database.db | 0 .../.universal/accessControls.ps1 | 27 + .../.universal/authentication.bak | 14 + .../.universal/authentication.bak20240802 | 87 + .../.universal/authentication.ps1 | 86 + .../.universal/dashboards.ps1 | 6 + .../.universal/endpoints.ps1 | 107 + .../.universal/environments.ps1 | 5 + .../.universal/loginPage.ps1 | 15 + .../.universal/publishedFolders.ps1 | 1 + .../.universal/roles.ps1 | 160 + .../.universal/schedules.ps1 | 13 + .../.universal/scripts.ps1 | 39 + .../.universal/settings.ps1 | 6 + .../.universal/tags.ps1 | 16 + .../.universal/triggers.ps1 | 1 + .../.universal/variables.ps1 | 12 + .../Get-ITDPSUAppNameTag.ps1 | 21 + .../New-ITDPSUScript.ps1 | 26 + .../New-ITDPSUVariable.ps1 | 15 + .../Set-ITDADUserDescription.ps1 | 3 + .../Set-ITDPSUScriptPermission.ps1 | 42 + .../Get-ITDModules.ps1 | 4 + .../ITD-PowerShellUniversal/Get-Service.ps1 | 2 + .../Get-UAJobVariable.ps1 | 21 + .../Test-PSUCredentials.ps1 | 6 + .../Test-PSUPlatformVariables.ps1 | 7 + .../Test-SQLThings.ps1 | 8 + .../Update-ITDModules.ps1 | 42 + .../ITD-PowerShellUniversal/zmtest.ps1 | 2 + .../Get-ITDServiceNowRecord_script.ps1 | 6 + .../Get-ITDServiceNowUser_script.ps1 | 22 + .../New-ITDServiceNowChangeRequest_test.ps1 | 124 + ...te-ITDServiceNowTaskDescription_script.ps1 | 26 + .../Approve-ITDWindowsServer_script.ps1 | 131 + .../Get-ITDExpiredFilesAuto_script.ps1 | 13 + .../New-ITDWindowsVmAzure_ManualExecution.ps1 | 59 + .../Remove-ITDExpiredFilesAuto_script.ps1 | 82 + .../Remove-ITDSolarwindsNode_script.ps1 | 10 + .../Remove-ITDWindowsServer_script.ps1 | 86 + .../Get-ITDExpiredFiles.ps1 | 13 + .../Remove-ITDExpiredFiles.ps1 | 119 + .../Approve-ITDWindowsServer.ps1 | 146 + .../New-ITDWindowsVmAzure_Manual.ps1 | 130 + .../New-ITDWindowsVmVMware_Manual.ps1 | 118 + .../Remove-ITDWindowsServer.ps1 | 92 + .../Test-WindowsServer.ps1 | 1 + .../New-ITDWindowsVmAzure_Step1.ps1 | 145 + .../New-ITDWindowsVmAzure_Step1.ps1.orig | 151 + .../New-ITDWindowsVmAzure_Step2.ps1 | 49 + .../New-ITDWindowsVmVMware_Step1.ps1 | 144 + .../New-ITDWindowsVmVMware_Step2.ps1 | 87 + .../New-ITDWindowsVm_Auto.ps1 | 146 + .../New-ITDWindowsVm_Step3.ps1 | 126 + .../Add-ITDADUserSPN.ps1 | 96 + .../Get-ITDADUser_script.ps1 | 9 + .../Get-ITDPassword_test.ps1 | 30 + .../New-ITDADServiceAccount.ps1 | 134 + .../New-ITDPassword_test.ps1 | 31 + .../Remove-ITDADUser.ps1 | 1 + .../Set-ITDSPN.ps1 | 1 + .../Add-ITDSolarwindsNode.ps1 | 31 + .../Remove-ITDSolarwindsNode.ps1 | 10 + .../Update-ITDSolarwindsNodeFromSNowRitm.ps1 | 38 + .../New-ITDPSUScript.ps1 | 34 + .../Update-ITDModule.ps1 | 42 + .../Get-ITDVMwareLunIdNextAvailable.ps1 | 1 + .../Get-ITDVMwareVMGuestIPsForPA.ps1 | 131 + .../Sync-ITDVMwareVMToSql.ps1 | 67 + .../New-ITDVMwareSnapshotTask.ps1 | 133 + ...New-ITDVMwareVMSnapshotExpiredIncident.ps1 | 59 + .../New-ITDVMwareVMSnapshotTask.ps1 | 133 + .../Remove-ITDVMwareVMSnapshotExpired.ps1 | 99 + .../Remove-ITDVMwareVMSnapshotTaskOrphan.ps1 | 3 + .../Test-ScriptPerms3.ps1 | 1 + .../Test-vCenterConnection.ps1 | 8 + .../Update-ITDVMwareVMSnapshotStatus.ps1 | 203 + .../Add-ITDServerBuildRitmToSql.ps1 | 90 + .../Approve-ITDVMNewBuild_script.ps1 | 85 + .../Move-ITDVMwareVMToAppNameFolder_Auto.ps1 | 46 + ...ew-ITDVMwareSharePointVMRecordFromRITM.ps1 | 28 + .../Set-ITDVMwareVMTagFromCmdb.ps1 | 58 + .../Sync-ITDServerBuildRITMs.ps1 | 158 + .../Sync-ITDVMwareVMMetadataToSharePoint.ps1 | 25 + ...ITDVMwareVMMetadataToSharePoint_script.ps1 | 15 + .../Sync-ITDVMwareVMTagsFromCmdb.ps1 | 10 + ...Update-ITDSNowVMTaskDescription_script.ps1 | 2 + .../Update-ITDSnowVMTaskDescription.ps1 | 2 + .../Shared-Powerschool/20240805dontest.ps1 | 1 + .../ZM-Test/Get-HelloWorld.ps1 | 6 + .../ZM-Test/New-ITDDummyFile.ps1 | 4 + .../ZM-Test/New-TestNestedInvoke.ps1 | 152 + .../ZM-Test/Test-FormSubmission.ps1 | 10 + .../ZM-Test/Test-ITDSchedule.ps1 | 77 + .../ZM-Test/Test-InvokeZM.ps1 | 5 + .../ZM-Test/Test-PSUVariable.ps1 | 2 + .../ZM-Test/Test-ServiceNowConnectivity.ps1 | 12 + .../ZM-Test/Test-ZM2.ps1 | 2 + .../ZM-Test/test-sql.ps1 | 18 + .../dashboards/Dashboard/Dashboard.ps1 | 3 + .../dashboards/Dashboard/pages/home.ps1 | 13 + .../DashboardTest/DashboardTest.ps1 | 23 + .../dashboards/DashboardTest/pages/home.ps1 | 3 + .../dashboards/DashboardTest/pages/test.ps1 | 10 + .../ITD-WindowsServer_FileManagement.ps1 | 25 + .../pages/PRD.ps1 | 30 + .../pages/home.ps1 | 3 + .../Infra-ActiveDirectory_Object.ps1 | 17 + .../Infra-ActiveDirectory.Object_NPD.ps1 | 4 + .../pages/groups.ps1 | 3 + .../pages/users.ps1 | 3 + .../Infra-VMware.Snapshot.ps1 | 30 + .../pages/LiveSnapshots.ps1 | 26 + .../Infra-VMware.Snapshot/pages/NPD.ps1 | 46 + .../Infra-VMware.Snapshot/pages/PRD.ps1 | 4 + .../Infra-VMware.Snapshot/pages/home.ps1 | 3 + .../Infra-VMware_Snapshot.ps1 | 30 + .../Infra-VMware_Snapshot/pages/PRD.ps1 | 57 + .../Infra-VMware_Snapshot/pages/home.ps1 | 3 + .../Infra-VMware_SnapshotReview.ps1 | 43 + .../pages/SnapshotReview.ps1 | 4 + .../NewITDADServiceAccount.ps1 | 13 + .../pages/ADServiceAccount.ps1 | 34 + .../NewITDADServiceAccount/pages/home.ps1 | 3 + .../NewITDADServiceAccountRequest.ps1 | 49 + .../pages/home.ps1 | 3 + .../NewITDVMwareVMSnapshotTask.ps1 | 16 + .../NewITDVMwareVMSnapshotTask/pages/home.ps1 | 3 + .../PSUVariableReview/PSUVariableReview.ps1 | 17 + .../PSUVariableReview/pages/home.ps1 | 3 + .../PSUVariableReview/pages/users.ps1 | 26 + .../dashboards/PSUVariables/PSUVariables.ps1 | 3 + .../dashboards/PSUVariables/pages/home.ps1 | 3 + .../RemoveITDExpiredFiles.ps1 | 3 + .../RemoveITDExpiredFiles/pages/home.ps1 | 3 + .../dashboards/ServiceNow/ServiceNow.ps1 | 33 + .../ServiceNow/pages/AppNameLookup.ps1 | 58 + .../ServiceNow/pages/ApplicationServerV2.ps1 | 25 + .../ServiceNow/pages/AzureVmSizeHelper.ps1 | 23 + .../ServiceNow/pages/CMDBServerList.ps1 | 154 + .../dashboards/ServiceNow/pages/CiLookup.ps1 | 97 + .../dashboards/ServiceNow/pages/CiTest.ps1 | 4 + .../ServiceNow/pages/ServerBuildRequestV1.ps1 | 39 + .../dashboards/ServiceNow/pages/home.ps1 | 11 + .../ServiceNowDumps/ServiceNowDumps.ps1 | 21 + .../pages/ApplicationServerV2.ps1 | 25 + .../dashboards/ServiceNowDumps/pages/Home.ps1 | 3 + .../pages/ServerBuildRequestV1.ps1 | 130 + .../ServiceNowDumps/pages/SpCmdbCompare.ps1 | 73 + .../dashboards/SyncTest/SyncTest.ps1 | 3 + .../dashboards/SyncTest/pages/home.ps1 | 3 + .../SyncVMwareVMtoSharePoint.ps1 | 29 + .../SyncVMwareVMtoSharePoint/pages/home.ps1 | 3 + .../TestMultiPage/TestMultiPage.ps1 | 17 + .../dashboards/TestMultiPage/pages/groups.ps1 | 3 + .../dashboards/TestMultiPage/pages/home.ps1 | 3 + .../dashboards/TestMultiPage/pages/users.ps1 | 3 + .../.universal/authentication.ps1 | 89 + .../.universal/roles.ps1 | 75 + .../.universal/scripts.ps1 | 4 + .../.universal/settings.ps1 | 5 + .../.universal/variables.ps1 | 2 + .../NewITDVMwareVMSnapshotTask.ps1 | 37 + .../Remove_ITDVmwareVMSnapshotExpired.ps1 | 1 + .../Update-ITDVMwareVMSnapshotStatus.ps1 | 1 + .../ZM-Test/Get-HelloWorld.ps1 | 3 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../ITD.Infra-VMware.Administration.old | 688 + .../ITD.Infra-VMware.Administration.nuspec | 9 + .../ITD.Infra-VMware.Administration.psd1 | 10 + .../ITD.Infra-VMware.Administration.psm1 | 23 + .../Public/Connect-ITDvCenter.ps1 | 36 + .../Public/Disable-ITDVMwareVMHostFeature.ps1 | 57 + .../Public/Disconnect-ITDvCenter.ps1 | 23 + .../Public/Enable-ITDVMwareVMHostFeature.ps1 | 57 + .../Public/Get-ITDSRMReport.ps1 | 33 + .../Public/Get-ITDVMwareDatastoreReport.ps1 | 58 + .../Public/Get-ITDVMwareSRMUsage.ps1 | 73 + .../Public/Get-ITDVMwareVMHAEventList.ps1 | 42 + .../Public/Get-ITDVMwareVMHostHBA.ps1 | 61 + .../Public/Get-ITDVMwareVMHostStatus.ps1 | 41 + .../Public/New-ITDVMNetwork.ps1 | 209 + .../Public/Remove-ITDVMwareCdDriveMedia.ps1 | 49 + ...ove-ITDVMwareOSCustomizationSpecOrphan.ps1 | 34 + .../Public/Set-ITDVMwareHostMaintenance.ps1 | 76 + .../ITD.Infra-VMware.Administration/README.md | 20 + ...VMware-SyncVMwareSharePointNetwork-prd.ps1 | 251 + .../VMBuilds/prod/Azure-ServicePrincipal.ps1 | 10 + .../prod/rb-Azure-NewAzureVMWindows-prd.ps1 | 843 + ...e-NewVMwareVMWindows-prd-InvokeTest.ps1old | 18 + .../prod/rb-VMware-NewVMwareVMWindows-prd.ps1 | 1102 + .../rb-VMware-NewVMwareVMWindows-prd.ps1-old | 1101 + .../test/rb-VMware-NewVMwareVMWindows-tst.ps1 | 358 + .../VMBuildsV2/AutoBuildInputFileExample.csv | 2 + .../Runbook/VMBuildsV2/New-ITDVMwareWindowsVM | 0 .../New-ITDVMwareWindowsVMFromCsv.ps1 | 64 + .../VMBuildsV2/rb-NewVMWindows-prd-Invoke.ps1 | 31 + .../VMBuildsV2/rb-NewVMWindows-prd.ps1 | 1131 + .../VMBuildsV2/rb-NewVM_CreateFile-prd.ps1 | 23 + .../rb-VMware-UpdateVMSnapshotStatus-prd.ps1 | 153 + .../prod/rb-VMware-NewVMSnapshotTask-prd.ps1 | 237 + .../prod/rb-VMware-RemoveVMSnapshot-prd.ps1 | 153 + .../rb-VMware-UpdateVMSnapshotStatus-prd.ps1 | 202 + .../Runbook/VMSnapshots/prod/snapshot.json | 6 + .../Runbook/VMSnapshots/prod/test.json | 11 + .../test/old/rb-VMware-RemoveVMSnapshot.ps1 | 168 + .../old/rb-VMware-UpdateVMCloneStatus.ps1 | 128 + .../rb-VMware-UpdateVMSnapshotStatus-old.ps1 | 127 + .../test/rb-VMware-NewVMSnapshotTask.ps1 | 216 + .../test/rb-VMware-RemoveVMSnapshot.ps1 | 164 + .../test/rb-VMware-UpdateVMSnapshotStatus.ps1 | 153 + .../Runbook/VMSnapshots/test/snapshot.json | 8 + .../Runbook/VMSnapshots/test/test.json | 6 + .../SRM/ITD.SRM.psm1 | 655 + .../SRM/SRMExportExample.xml | 43130 ++++++++++++++++ .../CohesityVMKernelsAndStaticRoutes.ps1 | 109 + .../Scripts/CommonTasks.ps1 | 404 + .../Scripts/GetIPs.ps1 | 97 + .../Scripts/GetIPsAzure.ps1 | 133 + .../Scripts/GetIPsAzureBackup.ps1 | 89 + .../Scripts/HPEILO-Certificates-V2.ps1 | 88 + .../Scripts/LockdownAndSSH.ps1 | 19 + .../Scripts/RollingRebootsWithHostProfile.ps1 | 102 + .../Scripts/ServiceNow-Sandbox.ps1 | 136 + .../Scripts/Storage Queries.ps1 | 75 + .../Sync-ITDOneViewServerInventoryToSql.ps1 | 270 + .../Sync-ITDVMwareClusterMetadataToSql.ps1 | 188 + .../Sync-ITDVMwareHostMetadataToSql.ps1 | 212 + .../Scripts/Sync-ITDVMwareVMMetadataToSql.ps1 | 299 + .../Scripts/VMHardening-Pub1075.ps1 | 95 + .../Scripts/VMHost-Decom.ps1 | 56 + .../Scripts/VMHost-GetWWNs.ps1 | 15 + .../VMHost-InitialHostConfiguration.ps1 | 188 + .../Scripts/VMHost-TestLocalCreds.ps1 | 38 + .../Scripts/VMhost-MetadataGeneration.ps1 | 3 + .../Scripts/VMhostPatching-BL460.ps1 | 363 + .../Scripts/VMhostPatching-Synergy.ps1 | 481 + .../Scripts/VMware-AutoBuildLoop.ps1 | 971 + .../Scripts/VMware-DisableLockdownVantis.ps1 | 41 + .../VMware-LockdownTicketAttemptFix.ps1 | 86 + .../Scripts/VMware-LockdownTickets.ps1 | 59 + .../Scripts/VMware-NewVMWindows.ps1 | 982 + .../Scripts/VMware-TagBladeLocation.ps1 | 18 + .../Scripts/VMware-TagVMs.ps1 | 245 + .../VMware-VMCpuMemoryClusterSRMReport.ps1 | 3 + .../VMware-VMDailyMetadataReport_Csv.ps1 | 177 + .../Scripts/VMware-VMSecureBoot.ps1 | 42 + .../Scripts/VMware-VMSecureBootB.ps1 | 42 + .../Scripts/VMware-vCenterUpgrade.ps1 | 71 + .../Scripts/vCenterUpgrade.ps1 | 13 + .../Tasks/CompareVMSRMList-Task.ps1 | 8 + .../Tasks/GetAzureVMGuestIPsForPA.ps1 | 146 + .../Tasks/GetVMwareVMGuestIPsForPA.ps1 | 122 + .../Tasks/Legacy/GetIPs.ps1 | 116 + .../Tasks/Legacy/GetIPsAzure.ps1 | 149 + .../Tasks/Legacy/GetIPsAzureBackup.ps1 | 104 + .../Tasks/Legacy/GetIPsMonitor.ps1 | 134 + .../Tasks/Legacy/vmconfig.ps1 | 87 + .../SetVMTagAndMoveToAppNameFolderTask.ps1 | 30 + .../Tasks/StartDatastoreUnmap.ps1 | 12 + ...yncVMwareAppNameTagsFromSharePointTask.ps1 | 28 + .../SyncVMwareDatastoresToSharePointTask.ps1 | 34 + .../Tasks/SyncVMwareHostTags.ps1 | 10 + .../SyncVMwareTagsFromSharePointTask.ps1 | 34 + .../Tasks/SyncVMwareVMsToSql.ps1 | 62 + .../Build/azure-pipelines.yml | 49 + .../ITD.Infra-VMware.Snapshot/Build/build.ps1 | 17 + .../ITD.Infra-VMware.Snapshot.nuspec | 12 + .../ITD.Infra-VMware.Snapshot.psd1 | 133 + .../ITD.Infra-VMware.Snapshot.psm1 | 23 + .../Public/New-ITDVMwareVMSnapshotTaskV3.ps1 | 143 + .../Public/New-ITDVMwareVMSnapshotV3.ps1 | 61 + .../Remove-ITDVMwareVMSnapshotTaskExpired.ps1 | 58 + .../Public/Remove-ITDVMwareVMSnapshotV3.ps1 | 42 + .../ITD.Infra-VMware.Snapshot/README.md | 20 + .../SQL/snapshottable.sql | 37 + .../NewITDVMwareVMSnapshotTask.ps1 | 23 + .../Build/azure-pipelines.yml | 49 + .../Build/build.ps1 | 17 + .../Approve-ITDVMNewBuild_script.ps1 | 85 + ...pprove-ITDVMNewBuild_scriptV3_DONOTUSE.ps1 | 89 + .../unused_to_review/New-ITDVMWindowsSNow.ps1 | 4 + .../New-ITDVMwareWindowsVMCsvFile.ps1 | 23 + .../New-ITDVMwareWindowsVMFromCsv.ps1 | 77 + .../VMware-WindowsVMTools.ps1 | 52 + .../unused_to_review/validate_newserver.ps1 | 45 + .../ITD.Infra-VMware.VirtualMachine.nuspec | 12 + .../ITD.Infra-VMware.VirtualMachine.psd1 | 133 + .../ITD.Infra-VMware.VirtualMachine.psm1 | 23 + .../Public/Approve-ITDVMNewBuild.ps1 | 140 + .../Compare-ITDVMwareVMTagsFromCmdb.ps1 | 137 + .../Public/Get-ITDVMwareVMAppNameTag.ps1 | 32 + .../Public/Get-ITDVMwareVMHardening.ps1 | 63 + .../Public/Get-ITDVMwareVMRPO.ps1 | 40 + .../Public/Get-ITDVMwareVMTagReport.ps1 | 122 + .../Public/Get-ITDVMwareVMToolsReport.ps1 | 71 + .../Move-ITDVMwareVMToAppNameFolder.ps1 | 59 + .../Public/New-ITDVMSNowRitm.ps1 | 282 + .../New-ITDVMwareSharePointVMRecord.ps1 | 193 + .../Public/Remove-ITDLinuxServer.ps1 | 80 + .../Public/Remove-ITDVMviaSNowTask.ps1 | 130 + .../Public/Set-ITDVMwareVMHardening.ps1 | 117 + .../Public/Set-ITDVMwareVMTag.ps1 | 330 + .../Public/Set-ITDVMwareVMTagFromCmdb.ps1 | 119 + .../Public/Set-ITDVMwareVMViaSnowTask.ps1 | 250 + .../Sync-ITDVMwareVMMetadataToSharePoint.ps1 | 239 + .../Public/Sync-ITDVMwareVMTagsFromCmdb.ps1 | 154 + .../Public/Update-ITDSNowVMTask.ps1 | 56 + .../Update-ITDSNowVMTaskDescription.ps1 | 169 + .../ITD.Infra-VMware.VirtualMachine/README.md | 20 + .../SQL/snapshottable.sql | 12 + ...Update-ITDSNowVMTaskDescription_script.ps1 | 2 + .../ITD.POC/Build/azure-pipelines.yml | 49 + _NDGOV_WindowsTeam/ITD.POC/Build/build.ps1 | 17 + _NDGOV_WindowsTeam/ITD.POC/Build/deploy.ps1 | 10 + _NDGOV_WindowsTeam/ITD.POC/ITD.POC.nuspec | 12 + _NDGOV_WindowsTeam/ITD.POC/ITD.POC.psd1 | 133 + _NDGOV_WindowsTeam/ITD.POC/ITD.POC.psm1 | 27 + .../ITD.POC/Private/Get-PrivateStuff.ps1 | 40 + .../Public/Get-PublicAndPrivateStuff.ps1 | 41 + .../ITD.POC/Public/Get-PublicStuff.ps1 | 37 + _NDGOV_WindowsTeam/ITD.POC/README.md | 20 + .../ITD.SQL.General/Build/azure-pipelines.yml | 49 + .../ITD.SQL.General/Build/build.ps1 | 17 + .../ITD.SQL.General/ITD.SQL.General.nuspec | 12 + .../ITD.SQL.General/ITD.SQL.General.psd1 | 132 + .../ITD.SQL.General/ITD.SQL.General.psm1 | 25 + .../Public/Invoke-ITDSqlCmdJob.ps1 | 65 + _NDGOV_WindowsTeam/ITD.SQL.General/README.md | 20 + .../Build/azure-pipelines.yml | 49 + .../ITD.Shared-ServiceNow/Build/build.ps1 | 17 + .../ITD.Shared-ServiceNow.nuspec | 12 + .../ITD.Shared-ServiceNow.psd1 | 132 + .../ITD.Shared-ServiceNow.psm1 | 25 + .../Private/Get-ITDServiceNowVariable.ps1 | 18 + .../Complete-ITDServiceNowChangeRequest.ps1 | 95 + ...et-ITDServiceNowChangeTemplateStandard.ps1 | 49 + .../Public/Get-ITDServiceNowRecord.ps1 | 281 + .../Public/Get-ITDServiceNowSession.ps1 | 32 + .../Public/Get-ITDServiceNowTable.ps1 | 56 + .../Public/Get-ITDServiceNowUser.ps1 | 56 + .../Public/Get-ITDServiceNowUserGroup.ps1 | 48 + .../Public/New-ITDServiceNowChangeRequest.ps1 | 246 + .../New-ITDServiceNowChangeRequestOG.ps1 | 202 + .../Public/New-ITDServiceNowIncident.ps1 | 120 + .../Public/New-ITDServiceNowRecord.ps1 | 41 + ...New-ITDServiceNowServiceCatalogRequest.ps1 | 116 + .../Public/New-ITDServiceNowSession.ps1 | 72 + .../Public/Update-ITDServiceNowRecord.ps1 | 118 + .../Scripts/API_Examples.ps1 | 492 + .../Scripts/CMDB tags key values.ps1 | 44 + .../CMDB_CI custom variable examples.ps1 | 170 + .../Scripts/Compare-ITDVMSharePointToCmdb.ps1 | 116 + .../Complete-ITDServiceNowIncident.ps1 | 21 + .../Scripts/Function_Examples.ps1 | 111 + .../Scripts/Get-ITDVMSharePointCmdbDiff.ps1 | 41 + 613 files changed, 140998 insertions(+) create mode 100644 _NDGOV_CS/ITD.Cohesity/.gitignore create mode 100644 _NDGOV_CS/ITD.Cohesity/README.md create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/AddRemoveVMTagIdsToProtectionGroup.ps1 create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.nuspec create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psd1 create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psm1 create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/README.md create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/Windows-ServiceRunAs.ps1 create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/addObjectToUserAccessList.ps1 create mode 100644 _NDGOV_CS/ITD.Cohesity/archive/powershell/cohesity-api.ps1 create mode 100644 _NDGOV_CS/ITD.Cohesity/azure-pipelines.yml create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/getSQLSourceErrorMessages.py create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/regexTest.py create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/systemHealth.py create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/temp-fixProtectionJobAttributes.py create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/template.py create mode 100644 _NDGOV_CS/ITD.Cohesity/beta/updateSQLProtectionJob_policy.py create mode 100644 _NDGOV_CS/ITD.Cohesity/cancelJobs.py create mode 100644 _NDGOV_CS/ITD.Cohesity/classes/automationsAPI.py create mode 100644 _NDGOV_CS/ITD.Cohesity/classes/cohesityAPI.py create mode 100644 _NDGOV_CS/ITD.Cohesity/classes/itdSnow.py create mode 100644 _NDGOV_CS/ITD.Cohesity/classes/serviceNowAPI.py create mode 100644 _NDGOV_CS/ITD.Cohesity/classes/sharePointAPI.py create mode 100644 _NDGOV_CS/ITD.Cohesity/dailyBackupReview.py create mode 100644 _NDGOV_CS/ITD.Cohesity/dailyErrors.py create mode 100644 _NDGOV_CS/ITD.Cohesity/dailyProtectionReview.py create mode 100644 _NDGOV_CS/ITD.Cohesity/diskAlerts.py create mode 100644 _NDGOV_CS/ITD.Cohesity/findDuplicates.py create mode 100644 _NDGOV_CS/ITD.Cohesity/pauseOrResumeJob.py create mode 100644 _NDGOV_CS/ITD.Cohesity/reNameJobs.py create mode 100644 _NDGOV_CS/ITD.Cohesity/registerServer.py create mode 100644 _NDGOV_CS/ITD.Cohesity/requirements.txt create mode 100644 _NDGOV_CS/ITD.Cohesity/sqlServerRegistration.py create mode 100644 _NDGOV_CS/ITD.Cohesity/template.py create mode 100644 _NDGOV_CS/ITD.Cohesity/unRegisterServer.py create mode 100644 _NDGOV_CS/ITD.Cohesity/updateAzPolicy.py create mode 100644 _NDGOV_CS/ITD.Cohesity/updateAzProtectionJobs.py create mode 100644 _NDGOV_CS/ITD.Cohesity/updateIndexingPolicy.py create mode 100644 _NDGOV_CS/ITD.Cohesity/updateProtectionGroupTags.py create mode 100644 _NDGOV_CS/ITD.Cohesity/vars/exemptions.yml create mode 100644 _NDGOV_CS/ITD.Cohesity/verified/validate_replication.py create mode 100644 _NDGOV_CS/ITDAzureRM/ITDAzureRM.psd1 create mode 100644 _NDGOV_CS/ITDAzureRM/ITDAzureRM.psm1 create mode 100644 _NDGOV_CS/ITDAzureRM/NewVMExistingDisk.ps1 create mode 100644 _NDGOV_CS/ZM1/README.md create mode 100644 _NDGOV_CS/ZM1/first-playbook.yml create mode 100644 _NDGOV_CS/cecogdill/snowSample.zip create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Public/ConvertTo-Array.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Public/Get-SslCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Public/Test-ADCredential.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Public/Uninstall-ITDModuleOldVersion.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/Public/Update-ITDModule.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.All-General/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/^template.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itddohslimst2.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappt01.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappu01.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdscmt1.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdvmvc1script.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdwinautot1.nd.gov.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.json create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.yml create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFilesSource.jsonbak create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Get-ITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Remove-ITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVm.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmAzure.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmVMware.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Private/New-ITDSSLCertificateSigningRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/New-ITDSSLCertificateSigningRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/Remove-ITDSolarwindsNode.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Scripts/DomainJoin_example.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/Remove-ITDWindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/DomainJoin_example.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/PSU_errorchecking.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Disable-ITDADUser.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADActiveServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADGroupMember.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADComputerServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADGroup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountOLD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountRitm.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Unlock-ITDADAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountFromSCTask_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountRITM_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccount_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/UD_PSU/NewITDADServiceAccountRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Data/Config.json create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Private/Set-OnLoad.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Download-SectigoCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Enroll-SectigoCertificateRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoApiToken.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificateTypes.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoOrg.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoSeverTypes.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Revoke-SectigoCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Test-SectigoCertificateRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/certmgr-api-doc-25.8.html create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Export-ITDPasswordList.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Find-ITDPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordAccountTypeId.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordList.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDRandomPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Remove-ITDPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Update-ITDPassword.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Passwordstate/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/Get-ITDServiceNowRecord create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/accessControls.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/authentication.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/dashboards.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/endpoints.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/loginPage.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/publishedFolders.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/roles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/schedules.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/scripts.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/settings.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/tags.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/variables.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles_Auto.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/Remove-ITDWindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Deploy-Client.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Get-RegistrationList .ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertAutoRenew.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertificateDeploy.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-ITDCertificateRequestSectigo.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Register-CommonName.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Troubleshooting.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Unregister-CommonName.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Update-Client.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDOneViewServerInventoryToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareClusterMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareHostMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareVMMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Update-ITDVMwareILOSslCertificate.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Get-HelloWorld.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/New-TestNestedInvoke.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-AzIaaSCredential.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDSchedule.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDScheduleWithCreds.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-InvokeZM.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-PSUVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMFile.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/test-sql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/PSUVariableReview.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/Users.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/ServiceNow.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AppNameLookup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CMDBServerList.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiLookup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiTest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/%ProgramData%/UniversalAutomation/database.db create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/accessControls.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak20240802 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/dashboards.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/endpoints.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/environments.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/loginPage.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/publishedFolders.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/roles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/schedules.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/scripts.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/settings.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/tags.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/triggers.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/variables.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Get-ITDPSUAppNameTag.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUScript.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDADUserDescription.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDPSUScriptPermission.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-ITDModules.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-Service.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-UAJobVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUCredentials.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUPlatformVariables.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-SQLThings.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Update-ITDModules.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/zmtest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowRecord_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowUser_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/New-ITDServiceNowChangeRequest_test.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Update-ITDServiceNowTaskDescription_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Approve-ITDWindowsServer_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Get-ITDExpiredFilesAuto_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/New-ITDWindowsVmAzure_ManualExecution.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDExpiredFilesAuto_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDSolarwindsNode_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDWindowsServer_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Remove-ITDWindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Test-WindowsServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDADUser_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDPassword_test.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDPassword_test.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Remove-ITDADUser.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Set-ITDSPN.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Sync-ITDVMwareVMToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotExpiredIncident.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotTaskOrphan.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-ScriptPerms3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-vCenterConnection.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Approve-ITDVMNewBuild_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/New-ITDVMwareSharePointVMRecordFromRITM.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSNowVMTaskDescription_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Shared-Powerschool/20240805dontest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Get-HelloWorld.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-ITDDummyFile.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-TestNestedInvoke.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-FormSubmission.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ITDSchedule.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-InvokeZM.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-PSUVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ServiceNowConnectivity.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ZM2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/test-sql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/Dashboard.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/DashboardTest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/test.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/Infra-ActiveDirectory_Object.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/Infra-ActiveDirectory.Object_NPD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/groups.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/users.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/Infra-VMware.Snapshot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/LiveSnapshots.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/NPD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/PRD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/Infra-VMware_SnapshotReview.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/pages/SnapshotReview.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/NewITDADServiceAccountRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/NewITDVMwareVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/PSUVariableReview.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/users.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/PSUVariables.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/ServiceNow.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AppNameLookup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CMDBServerList.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiLookup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiTest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/Home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/SpCmdbCompare.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/SyncTest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/SyncVMwareVMtoSharePoint.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/TestMultiPage.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/groups.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/home.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/users.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/authentication.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/roles.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/scripts.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/settings.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/variables.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/NewITDVMwareVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Remove_ITDVmwareVMSnapshotExpired.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/ZM-Test/Get-HelloWorld.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Helpers/ITD.Infra-VMware.Administration.old create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Connect-ITDvCenter.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disable-ITDVMwareVMHostFeature.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disconnect-ITDvCenter.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Enable-ITDVMwareVMHostFeature.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDSRMReport.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareDatastoreReport.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareSRMUsage.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHAEventList.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostHBA.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/New-ITDVMNetwork.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareCdDriveMedia.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareOSCustomizationSpecOrphan.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Set-ITDVMwareHostMaintenance.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/Networks/rb-VMware-SyncVMwareSharePointNetwork-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/Azure-ServicePrincipal.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-Azure-NewAzureVMWindows-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd-InvokeTest.ps1old create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1-old create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/test/rb-VMware-NewVMwareVMWindows-tst.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/AutoBuildInputFileExample.csv create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVM create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVMFromCsv.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd-Invoke.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVM_CreateFile-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/old/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-NewVMSnapshotTask-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-RemoveVMSnapshot-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/snapshot.json create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/test.json create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-RemoveVMSnapshot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMCloneStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMSnapshotStatus-old.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-NewVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-RemoveVMSnapshot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-UpdateVMSnapshotStatus.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/snapshot.json create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/test.json create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/ITD.SRM.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/SRMExportExample.xml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CohesityVMKernelsAndStaticRoutes.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CommonTasks.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzure.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzureBackup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/HPEILO-Certificates-V2.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/LockdownAndSSH.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/RollingRebootsWithHostProfile.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/ServiceNow-Sandbox.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Storage Queries.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDOneViewServerInventoryToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareClusterMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareHostMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareVMMetadataToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHardening-Pub1075.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-Decom.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-GetWWNs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-InitialHostConfiguration.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-TestLocalCreds.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhost-MetadataGeneration.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-BL460.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-Synergy.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-AutoBuildLoop.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-DisableLockdownVantis.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTicketAttemptFix.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTickets.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-NewVMWindows.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagBladeLocation.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagVMs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMCpuMemoryClusterSRMReport.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMDailyMetadataReport_Csv.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBoot.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBootB.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-vCenterUpgrade.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/vCenterUpgrade.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/CompareVMSRMList-Task.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetAzureVMGuestIPsForPA.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetVMwareVMGuestIPsForPA.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPs.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzure.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzureBackup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsMonitor.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/vmconfig.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SetVMTagAndMoveToAppNameFolderTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/StartDatastoreUnmap.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareAppNameTagsFromSharePointTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareDatastoresToSharePointTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareHostTags.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareTagsFromSharePointTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareVMsToSql.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotTaskV3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotV3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotTaskExpired.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotV3.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/SQL/snapshottable.sql create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Scripts_PSUDashboard/NewITDVMwareVMSnapshotTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_scriptV3_DONOTUSE.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMWindowsSNow.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMCsvFile.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMFromCsv.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/VMware-WindowsVMTools.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/validate_newserver.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Approve-ITDVMNewBuild.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Compare-ITDVMwareVMTagsFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMAppNameTag.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMHardening.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMRPO.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMTagReport.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMToolsReport.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Move-ITDVMwareVMToAppNameFolder.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMSNowRitm.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMwareSharePointVMRecord.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDLinuxServer.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDVMviaSNowTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMHardening.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTag.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTagFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMViaSnowTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMMetadataToSharePoint.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMTagsFromCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTask.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTaskDescription.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/SQL/snapshottable.sql create mode 100644 _NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Scripts_PSU/Update-ITDSNowVMTaskDescription_script.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Build/deploy.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/ITD.POC.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.POC/ITD.POC.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/ITD.POC.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Private/Get-PrivateStuff.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicAndPrivateStuff.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicStuff.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.POC/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/Public/Invoke-ITDSqlCmdJob.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.SQL.General/README.md create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/azure-pipelines.yml create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/build.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.nuspec create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psd1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psm1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Private/Get-ITDServiceNowVariable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Complete-ITDServiceNowChangeRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowChangeTemplateStandard.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowRecord.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowSession.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowTable.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUser.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUserGroup.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequestOG.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowIncident.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowRecord.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowServiceCatalogRequest.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowSession.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Update-ITDServiceNowRecord.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/API_Examples.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB tags key values.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB_CI custom variable examples.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Compare-ITDVMSharePointToCmdb.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Complete-ITDServiceNowIncident.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Function_Examples.ps1 create mode 100644 _NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Get-ITDVMSharePointCmdbDiff.ps1 diff --git a/_NDGOV_CS/ITD.Cohesity/.gitignore b/_NDGOV_CS/ITD.Cohesity/.gitignore new file mode 100644 index 0000000..59bf26e --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/.gitignore @@ -0,0 +1,4 @@ +*.swp +*.pyc +classes/__pycache__ +log/* diff --git a/_NDGOV_CS/ITD.Cohesity/README.md b/_NDGOV_CS/ITD.Cohesity/README.md new file mode 100644 index 0000000..a7940ce --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/README.md @@ -0,0 +1,110 @@ +NDIT Cohesity Scripts +------------------------- +These scripts factilitate the automation of NDIT's data protection program with Cohesity. Theses scripts are designed to be used by authorized North Dakota State NDIT personnel only. + +Contents +-------- +* classes/cohesityAPI.py + * Defines functions that have been tested and setup in accordance with NDIT Cohesity operating guidelines. + +* classes/serviceNowAPI.py + * Defines functions used for opening and assigning tickets for Cohesity issues + +* classes/sharePointAPI.py + * Defines functions used for looking up assets in the sharepoint configuration management database (CMDB) + +* cancelJobs.py + * Used for mass cancellation of all currently running jobs, typically used for vCenter maintenance. + +* dailyErrors.py + * Pulls all protection job runs for the previous 24 hours and creates ServiceNow tickets for any jobs in a Failure state + * Sends an email summary to the backup teams for all job states on a daily basis. + +* dailyProtectionReview.py + * Retrieves all VM objects from vCenter sources that are registerd to Cohesity and verifies that each object is protected or exempted in accordance with NDIT procedures. + * Reviews all protection jobs to ensure empty jobs are paused so they don't generate erroneous errors as well as ensures all popultated jobs are running. + * Creates SerivceNow Incidents for: + * Unprotected VMs + * Unprotected AppNames + * Populated Jobs that are paused + +* findDuplicates.py + * Pulls all backup jobs per vCenter and determines if a VM is listed in more than one group. + +* pauseOrResumeJob.py + * Used to mass pause or resume protectiong jobs, typically used for vCenter maintenance. + +* sqlServerRegistration.py + * Determines if the VM that identified by '-s' has been setup as a SQL server source, if not register it as one and add it to the appropriate SQL server protection group provided by CMDB lookup or specified by '-p'. + * Pull all kSQL object types within Cohesity and ensure the ITD-COHESITY-DBA group has access to all objects. + +* updateProtectionGroupTags.py + * Used to include or exclude vmWare protection job tags across a vCenter or individual job. + +* beta/getSQLSourceErrorMessages.py + * Pulls any failed health check information on SQL servers that could prevent the SQL server from getting backed up + * Attempts to refresh the source to eliminate false positives + * Opens a ServiceNow ticket if refreshing the source does not resolve the issue. + +ToDo +---- +* dailyProtectionReview.py + * BUG: + + * RFE: + * SeriveNow CMDB lookups will need to be used for AppName and exemnptions, see RFE 001 & RFE 002 sections in the script + +* dailyErrors.py + * RFE: + * Determine wheter or not we need to open tickets for jobs in a warning state. + +* findDuplicates.py + * RFE: + * Determine if this script needs to be ran on a routine basis. + * Add functionality to open tickets on duplicates + +* updateProtectionGroupTags.py + * RFE: + * Update API calls to use class calls instead of GetFilteredRequest() + * Update tag lookup section to use the function in the class instead of the local function in the script + +* sqlServerRegistration.py + * RFE: + * SeriveNow CMDB lookups will need to be used for AppName and exemnptions, see RFE 001 & RFE 002 sections in the script + * Update API calls to use class calls instead of GetFilteredRequest() + +Example Python Script +--------------------- +``` +import json +import sys +import certifi +import urllib3 + +from datetime import date, timedelta + +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity + +try: + + # Define create and instantiate the API for a Cohesity cluster + mdn = cohesity.API('itdmdndpc01.nd.gov') + + # Get the Auth Token and add it to the API header calls + mdnToken = mdn.GetAuthToken() + mdn.UpdateHeaders(mdnToken['accessToken']) + + # Get a list of objects from an API call, for a full listing of API calls, see developer.cohesity.com + vms = mdn.GetFilteredRequest("/public/protectionSources/virtualMachines", "?protected=true") + + # Print out an indented copy of the JSON data; use jsonparser.org or notepad++ to make it easier to read + print(json.dumps(vms, indent=4)) + + # Do something with the data based on the JSON output + for vm in vms: + print(vm['name']) + +except OSError as cohesityError: + print('Cohesity Error: ' + cohesityError) +``` diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/AddRemoveVMTagIdsToProtectionGroup.ps1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/AddRemoveVMTagIdsToProtectionGroup.ps1 new file mode 100644 index 0000000..aa6eee1 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/AddRemoveVMTagIdsToProtectionGroup.ps1 @@ -0,0 +1,98 @@ +# Add ExcludeVMTagIds +$AllProtectionSourceObject = Get-CohesityProtectionSourceObject +$AllProtectionGroups = Get-CohesityProtectionJob -Names "ZM-TEST" | Sort-Object Name + +ForEach ($ProtectionGroup in $AllProtectionGroups) { + Write-Warning ("Start " + $ProtectionGroup.name) + # Tag to Add to Exclude + $SourceObjectsToAddToExclude = $AllProtectionSourceObject | where-object { $_.Name -eq "Test" -and $_.ParentId -eq $ProtectionGroup.parentSourceId } + + If ($ProtectionGroup.excludeVmTagIds) { + # if an exclusion already exists + $ProtectionGroup.excludeVmTagIds += , @($SourceObjectsToAddToExclude.Id) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } Else { + # if an exclusion does not already exist + $ProtectionGroup | Add-Member -MemberType NoteProperty -Name excludeVmTagIds -Value @(, @($SourceObjectsToAddToExclude.Id)) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } +} + + + + + + + +# Remove ExcludeVMTagIds +$AllProtectionSourceObject = Get-CohesityProtectionSourceObject +$AllProtectionGroups = Get-CohesityProtectionJob -Names "ZM-TEST" | Sort-Object Name + +ForEach ($ProtectionGroup in $AllProtectionGroups) { + Write-Warning ("Start " + $ProtectionGroup.name) + # Tag to Remove to Exclude + $SourceObjectsToRemoveFromExclude = $AllProtectionSourceObject | Where-Object { $_.Name -eq "Test" -and $_.ParentId -eq $ProtectionGroup.parentSourceId } + + if (! $ProtectionGroup.PSObject.Properties['excludeVmTagIds']) { + + } + else { + $NewArray = @() + ForEach ($item in $ProtectionGroup.PSObject.Properties['excludeVmTagIds'].value) { + if ($item -ne $SourceObjectsToRemoveFromExclude.id) { $NewArray += $item } + } + + If(@($NewArray).count -gt 0){ + $ProtectionGroup.excludeVmTagIds = ,@($NewArray) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } + If(@($NewArray).count -eq 0){ + $ProtectionGroup.PSObject.Properties.remove('excludeVmTagIds') + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } + } +} + + + +# Add VMTagIds +$AllProtectionSourceObject = Get-CohesityProtectionSourceObject +$AllProtectionGroups = Get-CohesityProtectionJob -Names "ZM-TEST" | Sort-Object Name + +ForEach ($ProtectionGroup in $AllProtectionGroups) { + Write-Warning ("Start " + $ProtectionGroup.name) + # Tag to Add to Include + $SourceObjectsToAddToInclude = $AllProtectionSourceObject | where-object { $_.Name -eq "ITD-POC-Video" -and $_.ParentId -eq $ProtectionGroup.parentSourceId } + + If ($ProtectionGroup.VmTagIds) { + # if an exclusion already exists + $ProtectionGroup.VmTagIds += , @($SourceObjectsToAddToInclude.Id) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } Else { + # if an exclusion does not already exist + $ProtectionGroup | Add-Member -MemberType NoteProperty -Name VmTagIds -Value @(, @($SourceObjectsToAddToInclude.Id)) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } +} + + + +# Remove VMTagIds +$AllProtectionSourceObject = Get-CohesityProtectionSourceObject +$AllProtectionGroups = Get-CohesityProtectionJob -Names "ZM-TEST" | Sort-Object Name + +ForEach ($ProtectionGroup in $AllProtectionGroups) { + Write-Warning ("Start " + $ProtectionGroup.name) + # Tag to Remove from Include + $SourceObjectsToRemoveFromInclude = $AllProtectionSourceObject | where-object { $_.Name -eq "ITD-POC-Video" -and $_.ParentId -eq $ProtectionGroup.parentSourceId } + + If ($ProtectionGroup.VmTagIds) { + # if an exclusion already exists + $ProtectionGroup.VmTagIds += , @($SourceObjectsToRemoveFromInclude.Id) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } Else { + # if an exclusion does not already exist + $ProtectionGroup | Add-Member -MemberType NoteProperty -Name VmTagIds -Value @(, @($SourceObjectsToRemoveFromInclude.Id)) + Set-CohesityProtectionJob -ProtectionJob $ProtectionGroup -confirm:$false + } +} \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.nuspec b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.nuspec new file mode 100644 index 0000000..b9df512 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.nuspec @@ -0,0 +1,9 @@ + + + + ITD.Cohesity + $VERSIONHERE$ + Cliff Cogdill / Zack Meier + Functions for Cohesity administration + + \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psd1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psd1 new file mode 100644 index 0000000..5f93fdc --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psd1 @@ -0,0 +1,10 @@ +@{ + RootModule = 'ITD.Cohesity.psm1' + ModuleVersion = '' + GUID = '9b7f0813-ae13-4d3b-9b5a-608374755382' + Author = 'Cliff Cogdill / Zack Meier ' + CompanyName = 'State of North Dakota' + PowerShellVersion = '7' + CompatiblePSEditions = 'Desktop','Core' + FunctionsToExport = @() +} \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psm1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psm1 new file mode 100644 index 0000000..8ebebcc --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/ITD.Cohesity.psm1 @@ -0,0 +1,116 @@ +<# +.SYNOPSIS + Run a single on-demand VMware incremental backup +.DESCRIPTION + Run a single on-demand VMware incremental backup +.EXAMPLE + Start-ITDCohesityOnDemandVMIncremental -ComputerName itdxyz.nd.gov +.NOTES + General notes +.COMPONENT + Cohesity +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Start-ITDCohesityOnDemandVMIncremental { + [CmdletBinding()] + Param ( + + [Parameter()] + $ComputerName + ) + + begin { + } + + process { + $CohesityVMwareVM = Get-CohesityProtectionSourceObject | Where-Object Name -eq $ComputerName #| Select-Object -Unique Id, Name, Environment, ParentId + Start-CohesityProtectionJob -Id (Get-CohesityProtectionJob | Where-Object sourceIds -Match $CohesityVmwareVM.parentId) -SourceIds $CohesityVMwareVM.id + } + + end { + + } +} + +<# +.SYNOPSIS + Create a Protection Group based on VMware AppName Tag, one protection group for each VMware source. +.DESCRIPTION + Long description +.EXAMPLE + New-ITDCohesityProtectionGroup -AppName ITD-POC-zmeier +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function New-ITDCohesityProtectionGroupWIP { + [CmdletBinding()] + Param ( + [Parameter()] + [string[]] + $AppName, + + [switch] + $NewBuildsOnly + ) + + begin { + } + + process { + $AllProtectionSourceObject = Get-CohesityProtectionSourceObject + # create protection group based on appname, exclude placeholders + ForEach ($app in $AppName) { + $ProtectionJob = $null + + $SourceObjects = $AllProtectionSourceObject | Where-Object Name -eq $app + $StartHour = Get-Random -Minimum 18 -Maximum 23 + $StartDateTime = ([DateTime]::Today.AddHours($StartHour)).AddMinutes(30) + ForEach ($SourceObject in $SourceObjects) { + $Source = Get-CohesityProtectionSourceObject -Id $SourceObject.parentId + switch ($Source.environment) { + 'kVMware' { + $ProtectionJobName = ($app + "@" + $Source.Name.split('.')[0]) + } + 'kPhysical' { + $ProtectionJobName = ($app + "@" + "physical") + } + } + + $SRMTagPlaceholderObject = $AllProtectionSourceObject | Where-Object {$_.Name -eq "Placeholder" -and $_.ParentId -eq $SourceObject.parentId} + + New-CohesityProtectionJob -Name $ProtectionJobName ` + -PolicyName "ITD-Bronze" ` + -VmTagIds $SourceObject.Id ` + -ParentSourceId $SourceObject.parentId ` + -ExcludeVmTagIds $SRMTagPlaceholderObject.id ` + -Environment $Source.environment ` + -Timezone "America/Chicago" ` + -ScheduleStartTime $StartDateTime ` + -StorageDomainName DefaultStorageDomain ` + + $indexingPolicy = [PSCustomObject]@{ + disableIndexing = $false; + allowPrefixes = @('/'); + denyPrefixes = @('/$Recycle.Bin', '/Windows', '/ProgramData', '/System Volume Information', '/Users/*/AppData', '/Recovery', '/usr', '/sys', '/proc', '/lib', '/grub', '/grub2', 'opt/splunk', '/splunk') + } + + $ProtectionJob = Get-CohesityProtectionJob -Names $ProtectionJobName + $ProtectionJob | Add-Member -MemberType NoteProperty -Name indexingPolicy -Value $indexingPolicy + Set-CohesityProtectionJob -ProtectionJob $ProtectionJob -Confirm:$false + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/README.md b/_NDGOV_CS/ITD.Cohesity/archive/powershell/README.md new file mode 100644 index 0000000..6755aab --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/README.md @@ -0,0 +1,31 @@ +# Add backup object to Cohesity User and Groups +This script lists users and groups and writes the output to a text file (addObjectToUserAccessList-clusterName.txt) + +# Components + - addObjectToUserAccessList.ps1: the main powershell script + - cohesity-api.ps1: the Cohesity REST API helper module + +Place the files in a folder together and run the main script like so: + +# Command line example +``` +./addObjectToUserAccessList.ps1 -vip mycluster ` + -username myuser ` + -domain mydomain.net ` + -principal mydomain.net/myuser ` + -addObject vm1, server1.mydomain.net ` + -removeObject vm2, vm3 ` + -addView view1, view2 ` + -removeView view3, view4 +``` + +# Parameters + +- vip: Cohesity Cluster to connect to +- username: Cohesity username +- domain: (optional) Cohesity logon domain (defaults to local) +- principal: name(s) (comma separated) of user or group to modify (e.g. mydomain.net/myuser, or mylocaluser) +- addObject: (optional) names of registered objects to add to access list (comma separated) +- removeObject: (optional) names of registered objects to remove from access list (comma separated) +- addView: (optional) names of views to add to access list (comma separated) +- removeView: (optional) names of views to remove from access list (comma separated) diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/Windows-ServiceRunAs.ps1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/Windows-ServiceRunAs.ps1 new file mode 100644 index 0000000..596f147 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/Windows-ServiceRunAs.ps1 @@ -0,0 +1,27 @@ +#Add to Local Security Policy +function Add-ServiceLogonRight([string] $Username) { + Write-Host "Enable ServiceLogonRight for $Username" + + $tmp = New-TemporaryFile + secedit /export /cfg "$tmp.inf" | Out-Null + (Get-Content -Encoding ascii "$tmp.inf") -replace '^SeServiceLogonRight .+', "`$0,$Username" | sc -Encoding ascii "$tmp.inf" + secedit /import /cfg "$tmp.inf" /db "$tmp.sdb" | Out-Null + secedit /configure /db "$tmp.sdb" /cfg "$tmp.inf" | Out-Null + Remove-Item $tmp* -ea 0 +} + +Add-ServiceLogonRight -Username svccohesityadm + + +sc.exe config "CohesityAgent" obj="NDGOV\svccohesityadm" password="xxxxxxxxx" + + + + + + +#Prompt for secure password & convert to plaintext for DataStage use +$dsSecurePass = Read-Host -AsSecureString "Enter $($dsUser) password" +$dsBinaryPass = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($dsSecurePass) +$dsPass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($dsBinaryPass) +[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($dsBinaryPass) \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/addObjectToUserAccessList.ps1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/addObjectToUserAccessList.ps1 new file mode 100644 index 0000000..60ee2e1 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/addObjectToUserAccessList.ps1 @@ -0,0 +1,120 @@ +### process commandline arguments +[CmdletBinding()] +param ( + [Parameter(Mandatory = $True)][string]$vip, #the cluster to connect to (DNS name or IP) + [Parameter(Mandatory = $True)][string]$username, #username (local or AD) + [Parameter()][string]$domain = 'local', #local or AD domain + [Parameter()][array]$principal, + [Parameter()][array]$addObject, + [Parameter()][array]$addView, + [Parameter()][array]$removeObject, + [Parameter()][array]$removeView +) + +### source the cohesity-api helper code +. $(Join-Path -Path $PSScriptRoot -ChildPath cohesity-api.ps1) + +### authenticate +apiauth -vip $vip -username $username -domain $domain + +$users = api get users?_includeTenantInfo=true +$groups = api get groups?_includeTenantInfo=true +$sources = api get "protectionSources" +$views = api get views + +function getObjectId($objectName){ + $global:_object_id = $null + + function get_nodes($obj){ + if($obj.protectionSource.name -eq $objectName){ + $global:_object_id = $obj.protectionSource.id + break + } + if($obj.name -eq $objectName){ + $global:_object_id = $obj.id + break + } + if($obj.PSObject.Properties['nodes']){ + foreach($node in $obj.nodes){ + if($null -eq $global:_object_id){ + get_nodes $node + } + } + } + } + + foreach($source in $sources){ + if($null -eq $global:_object_id){ + get_nodes $source + } + } + return $global:_object_id +} + + +foreach($p in $principal){ + if($p -match '/'){ + $d, $p = $p.split('/') + }else{ + $d = 'local' + } + $ptype = 'user' + $thisPrincipal = $users | Where-Object {$_.username -eq $p -and $_.domain -eq $d} + if(!$thisPrincipal){ + $ptype = 'group' + $thisPrincipal = $groups | Where-Object {$_.name -eq $p -and $_.domain -eq $d} + } + if(!$thisPrincipal){ + Write-Host "Principal $d/$p not found!" -ForegroundColor Yellow + continue + } + $access = api get principals/protectionSources?sids=$($thisPrincipal.sid) + $newAccess = @{ + "sourcesForPrincipals" = @( + @{ + "sid" = $thisPrincipal.sid; + "protectionSourceIds" = [array]$access.protectionSources.id; + "viewNames" = [array]$access.views.name + } + ) + } + foreach($objectName in $addObject){ + $objectId = getObjectId $objectName + if(!$objectId){ + Write-Host "Object $objectName not found!" -ForegroundColor Yellow + continue + } + "Adding $objectName" + $newAccess.sourcesForPrincipals[0].protectionSourceIds = @($newAccess.sourcesForPrincipals[0].protectionSourceIds + $objectId) + } + foreach($objectName in $removeObject){ + $objectId = getObjectId $objectName + if($objectId){ + "Removing $objectName" + $newAccess.sourcesForPrincipals[0].protectionSourceIds = @($newAccess.sourcesForPrincipals[0].protectionSourceIds | Where-Object {$_ -ne $objectId}) + } + } + foreach($viewName in $addView){ + $view = $views.views | Where-Object {$_.name -eq $viewName} + if(!$view){ + Write-Host "View $viewName not found" -ForegroundColor Yellow + continue + } + "Adding $viewName" + $newAccess.sourcesForPrincipals[0].viewNames = @($newAccess.sourcesForPrincipals[0].viewNames + $view.name) + } + foreach($viewName in $removeView){ + "Removing $viewName" + $newAccess.sourcesForPrincipals[0].viewNames = @($newAccess.sourcesForPrincipals[0].viewNames | Where-Object {$_ -ne $viewName}) + } + $newAccess.sourcesForPrincipals[0].protectionSourceIds = @($newAccess.sourcesForPrincipals[0].protectionSourceIds | Sort-Object -Unique) + $newAccess.sourcesForPrincipals[0].viewNames = @($newAccess.sourcesForPrincipals[0].viewNames | Sort-Object -Unique) + $thisPrincipal.restricted = $True + if($ptype -eq 'user'){ + $null = api put users $thisPrincipal + }else{ + $null = api put groups $thisPrincipal + } + $null = api put principals/protectionSources $newAccess +} + diff --git a/_NDGOV_CS/ITD.Cohesity/archive/powershell/cohesity-api.ps1 b/_NDGOV_CS/ITD.Cohesity/archive/powershell/cohesity-api.ps1 new file mode 100644 index 0000000..b108f64 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/archive/powershell/cohesity-api.ps1 @@ -0,0 +1,813 @@ +# . . . . . . . . . . . . . . . . . . . +# PowerShell Module for Cohesity API +# Version 2020.12.22 - Brian Seltzer +# . . . . . . . . . . . . . . . . . . . +# +# 2020.10.16 - added password parameter to storePasswordInFile function +# 2020.10.20 - code cleanup (moved old version history to end of file) +# 2020.12.22 - added v2 support for file download +# +# . . . . . . . . . . . . . . . . . . . . . . . . +$versionCohesityAPI = '2020.12.22' + +# demand modern powershell version (must support TLSv1.2) +if($Host.Version.Major -le 5 -and $Host.Version.Minor -lt 1){ + Write-Warning "PowerShell version must be upgraded to 5.1 or higher to connect to Cohesity!" + Pause + exit +} + +$REPORTAPIERRORS = $true + +$pwfile = $(Join-Path -Path $PSScriptRoot -ChildPath YWRtaW4) +$apilogfile = $(Join-Path -Path $PSScriptRoot -ChildPath cohesity-api-debug.log) + +# platform detection ========================================================================== +if ($PSVersionTable.Platform -eq 'Unix') { + $CONFDIR = '~/.cohesity-api' + if ($(Test-Path $CONFDIR) -eq $false) { $null = New-Item -Type Directory -Path $CONFDIR} +}else{ + $registryPath = 'HKCU:\Software\Cohesity-API' + $WEBCLI = New-Object System.Net.WebClient; +} + +if($PSVersionTable.PSEdition -eq 'Desktop'){ + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true } + $ignoreCerts = @" +public class SSLHandler +{ + public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler() + { + return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; }); + } +} +"@ + + if(!("SSLHandler" -as [type])){ + Add-Type -TypeDefinition $ignoreCerts + } + [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler() +} + +function __writeLog($logmessage){ + "$(Get-Date): $logmessage" | Out-File -FilePath $apilogfile -Append +} + +# authentication functions ======================================================================== + +function apiauth($vip, $username='helios', $domain='local', $passwd=$null, $password = $null, $tenantId = $null, [switch] $quiet, [switch] $noprompt, [switch] $updatePassword, [switch] $helios, [switch] $useApiKey){ + + if(-not $vip){ + if($helios){ + $vip = 'helios.cohesity.com' + }else{ + Write-Host 'vip is required' -foregroundcolor Yellow + break + } + } + + # parse domain\username or username@domain + if($username.Contains('\')){ + $domain, $username = $username.Split('\') + } + if($password){ $passwd = $password } + if($updatePassword){ + $fpasswd = Get-CohesityAPIPasswordFromFile -vip $vip -username $username -domain $domain + if($fpasswd){ + storePasswordInFile -vip $vip -username $username -domain $domain + }else{ + Set-CohesityAPIPassword -vip $vip -username $username -domain $domain + } + } + # get password + if(!$passwd){ + $passwd = Get-CohesityAPIPassword -vip $vip -username $username -domain $domain + if(!$passwd -and !$noprompt){ + Set-CohesityAPIPassword -vip $vip -username $username -domain $domain + $passwd = Get-CohesityAPIPassword -vip $vip -username $username -domain $domain + } + if(!$passwd){ + Write-Host "No password provided for $username at $vip" -ForegroundColor Yellow + $global:AUTHORIZED = $false + break + } + } + + $body = ConvertTo-Json @{ + 'domain' = $domain; + 'username' = $username; + 'password' = $passwd + } + + $global:APIROOT = 'https://' + $vip + '/irisservices/api/v1' + $global:APIROOTv2 = 'https://' + $vip + '/v2/' + $HEADER = @{'accept' = 'application/json'; 'content-type' = 'application/json'} + if($useApiKey){ + $HEADER['apiKey'] = $passwd + $global:HEADER = $HEADER + $global:AUTHORIZED = $true + $global:CLUSTERSELECTED = $true + $cluster = api get cluster + if($cluster){ + if(!$quiet){ Write-Host "Connected!" -foregroundcolor green } + }else{ + $global:AUTHORIZED = $false + } + }elseif($vip -eq 'helios.cohesity.com' -or $helios){ + # Authenticate Helios + $HEADER['apiKey'] = $passwd + $URL = 'https://helios.cohesity.com/mcm/clusters/connectionStatus' + try{ + if($PSVersionTable.Edition -eq 'Core'){ + $global:HELIOSALLCLUSTERS = Invoke-RestMethod -Method get -Uri $URL -Header $HEADER -SkipCertificateCheck + }else{ + $global:HELIOSALLCLUSTERS = Invoke-RestMethod -Method get -Uri $URL -Header $HEADER + } + $global:HELIOSCONNECTEDCLUSTERS = $global:HELIOSALLCLUSTERS | Where-Object connectedToCluster -eq $true + $global:HEADER = $HEADER + $global:AUTHORIZED = $true + $global:CLUSTERSELECTED = $false + $global:CLUSTERREADONLY = $false + if(!$quiet){ Write-Host "Connected!" -foregroundcolor green } + }catch{ + $global:AUTHORIZED = $false + __writeLog $_.ToString() + if($_.ToString().contains('"message":')){ + Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow + }else{ + Write-Host $_.ToString() -foregroundcolor yellow + } + } + }else{ + # Authenticate Cluster + $url = $APIROOT + '/public/accessTokens' + try { + # authenticate + if($PSVersionTable.PSEdition -eq 'Core'){ + $auth = Invoke-RestMethod -Method Post -Uri $url -Header $HEADER -Body $body -SkipCertificateCheck + }else{ + $auth = Invoke-RestMethod -Method Post -Uri $url -Header $HEADER -Body $body + } + # set file transfer details + if($PSVersionTable.Platform -eq 'Unix'){ + $global:CURLHEADER = "authorization: $($auth.tokenType) $($auth.accessToken)" + }else{ + $WEBCLI.Headers['authorization'] = $auth.tokenType + ' ' + $auth.accessToken; + } + # store token + $global:AUTHORIZED = $true + $global:CLUSTERSELECTED = $true + $global:CLUSTERREADONLY = $false + $global:HEADER = @{'accept' = 'application/json'; + 'content-type' = 'application/json'; + 'authorization' = $auth.tokenType + ' ' + $auth.accessToken + } + if($tenantId){ + $global:HEADER['x-impersonate-tenant-id'] = "$tenantId/" + } + if(!$quiet){ Write-Host "Connected!" -foregroundcolor green } + }catch{ + $global:AUTHORIZED = $false + __writeLog $_.ToString() + $global:AUTHORIZED = $false + if($REPORTAPIERRORS){ + if($_.ToString().contains('"message":')){ + Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow + }else{ + Write-Host $_.ToString() -foregroundcolor yellow + } + } + } + } +} + +# select helios access cluster +function heliosCluster($clusterName, [switch] $verbose){ + if($clusterName -and $HELIOSCONNECTEDCLUSTERS){ + if(! ($clusterName -is [string])){ + $clusterName = $clusterName.name + } + $cluster = $HELIOSCONNECTEDCLUSTERS | Where-Object name -eq $clusterName + if($cluster){ + $global:HEADER.accessClusterId = $cluster.clusterId + $global:CLUSTERSELECTED = $true + $global:CLUSTERREADONLY = (api get /mcm/config).mcmReadOnly + if($verbose){ + Write-Host "Connected ($($cluster.name))" -ForegroundColor Green + } + }else{ + Write-Host "Cluster $clusterName not connected to Helios" -ForegroundColor Yellow + $global:CLUSTERSELECTED = $false + return $null + } + }else{ + $HELIOSCONNECTEDCLUSTERS | Sort-Object -Property name | Select-Object -Property name, clusterId, softwareVersion + "`ntype heliosCluster to connect to a cluster" + } + if (-not $global:AUTHORIZED){ + if($REPORTAPIERRORS){ + Write-Host 'Please use apiauth to connect to helios' -foregroundcolor yellow + } + } +} + +function heliosClusters(){ + return $HELIOSCONNECTEDCLUSTERS | Sort-Object -Property name +} + +# terminate authentication +function apidrop([switch] $quiet){ + $global:AUTHORIZED = $false + $global:HEADER = '' + $global:HELIOSALLCLUSTERS = $null + $global:HELIOSCONNECTEDCLUSTERS = $null + if(!$quiet){ Write-Host "Disonnected!" -foregroundcolor green } +} + +# api call functions ============================================================================== + +$methods = 'get', 'post', 'put', 'delete' +function api($method, $uri, $data, $version=1, [switch]$v2){ + if (-not $global:AUTHORIZED){ + if($REPORTAPIERRORS){ + Write-Host 'Not authenticated to a cohesity cluster' -foregroundcolor yellow + if($MyInvocation.PSCommandPath){ + exit 1 + } + } + }else{ + if($method -ne 'get' -and $global:CLUSTERREADONLY -eq $true){ + Write-Host "Cluster connection is READ-ONLY" -ForegroundColor Yellow + break + } + if (-not $methods.Contains($method)){ + if($REPORTAPIERRORS){ + Write-Host "invalid api method: $method" -foregroundcolor yellow + } + break + } + try { + + if($version -eq 2 -or $v2){ + $url = $APIROOTv2 + $uri + }else{ + if ($uri[0] -ne '/'){ $uri = '/public/' + $uri} + $url = $APIROOT + $uri + } + $body = ConvertTo-Json -Depth 100 $data + if ($PSVersionTable.PSEdition -eq 'Core'){ + if($body){ + $result = Invoke-RestMethod -Method $method -Uri $url -Body $body -Header $HEADER -SkipCertificateCheck + }else{ + $result = Invoke-RestMethod -Method $method -Uri $url -Header $HEADER -SkipCertificateCheck + } + }else{ + $result = Invoke-RestMethod -Method $method -Uri $url -Body $body -Header $HEADER + } + return $result + }catch{ + __writeLog $_.ToString() + if($REPORTAPIERRORS){ + if($_.ToString().contains('"message":')){ + Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow + }else{ + Write-Host $_.ToString() -foregroundcolor yellow + } + } + } + } +} + +# file download function +function fileDownload($uri, $fileName, $version=1, [switch]$v2){ + if (-not $global:AUTHORIZED){ Write-Host 'Please use apiauth to connect to a cohesity cluster' -foregroundcolor yellow; break } + try { + if($version -eq 2 -or $v2){ + $url = $APIROOTv2 + $uri + }else{ + if ($uri[0] -ne '/'){ $uri = '/public/' + $uri} + $url = $APIROOT + $uri + } + if ($PSVersionTable.Platform -eq 'Unix'){ + curl -k -s -H "$global:CURLHEADER" -o "$fileName" "$url" + }else{ + if($fileName -notmatch '\\'){ + $fileName = $(Join-Path -Path $PSScriptRoot -ChildPath $fileName) + } + $WEBCLI.DownloadFile($url, $fileName) + } + }catch{ + __writeLog $_.ToString() + $_.ToString() + if($_.ToString().contains('"message":')){ + Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow + }else{ + Write-Host $_.ToString() -foregroundcolor yellow + } + } +} + +# date functions ================================================================================== + +function timeAgo([int64] $age, [string] $units){ + $currentTime = [int64](((get-date).ToUniversalTime())-([datetime]"1970-01-01 00:00:00")).TotalSeconds*1000000 + $secs=@{'seconds'= 1; 'sec'= 1; 'secs' = 1; + 'minutes' = 60; 'min' = 60; 'mins' = 60; + 'hours' = 3600; 'hour' = 3600; + 'days' = 86400; 'day' = 86400; + 'weeks' = 604800; 'week' = 604800; + 'months' = 2628000; 'month' = 2628000; + 'years' = 31536000; 'year' = 31536000 } + $age = $age * $secs[$units.ToLower()] * 1000000 + return [int64] ($currentTime - $age) +} + +function usecsToDate($usecs){ + $unixTime=$usecs/1000000 + $origin = ([datetime]'1970-01-01 00:00:00') + return $origin.AddSeconds($unixTime).ToLocalTime() +} + +function dateToUsecs($datestring){ + if($datestring -isnot [datetime]){ $datestring = [datetime] $datestring } + $usecs = [int64](($datestring.ToUniversalTime())-([datetime]"1970-01-01 00:00:00")).TotalSeconds*1000000 + $usecs +} + +# password functions ============================================================================== + +function Get-CohesityAPIPassword($vip, $username, $domain='local'){ + # parse domain\username or username@domain + if($username.Contains('\')){ + $domain, $username = $username.Split('\') + } + if($username.Contains('@')){ + $username, $domain = $username.Split('@') + } + $passwd = Get-CohesityAPIPasswordFromFile -vip $vip -username $username -domain $domain + if($passwd){ + return $passwd + } + $keyName = "$vip`:$domain`:$username" + if($PSVersionTable.Platform -eq 'Unix'){ + # Unix + $keyFile = "$CONFDIR/$keyName" + if (Test-Path $keyFile) { + $key, $storedPassword = Get-Content $keyFile + return Unprotect-CohesityAPIPassword $key $storedPassword + } + }else{ + # Windows + $storedPassword = Get-ItemProperty -Path "$registryPath" -Name "$keyName" -ErrorAction SilentlyContinue + If (($null -ne $storedPassword) -and ($storedPassword.Length -ne 0)) { + $securePassword = $storedPassword.$keyName | ConvertTo-SecureString + return [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $securePassword )) + } + } +} + + +function Get-CohesityAPIPasswordFromFile($vip, $username, $domain){ + $pwlist = Get-Content -Path $pwfile -ErrorAction SilentlyContinue + foreach($pwitem in $pwlist){ + $v, $d, $u, $cpwd = $pwitem.split(":", 4) + if($v -eq $vip -and $d -eq $domain -and $u -eq $username){ + return [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($cpwd)) + } + } + return $null +} + + +function storePasswordInFile($vip='helios.cohesity.com', $username='helios', $domain='local', [switch]$helios, $password=$null){ + # parse domain\username or username@domain + if($username.Contains('\')){ + $domain, $username = $username.Split('\') + } + if($username.Contains('@')){ + $username, $domain = $username.Split('@') + } + + if($vip -eq 'helios.cohesity.com' -and $username -eq 'helios' -and ! $helios){ + # prompt for vip + __writeLog "Prompting for VIP, USERNAME, DOMAIN" + $newVip = Read-Host -Prompt "Enter VIP ($vip)" + if($newVip -ne ''){ $vip = $newVip } + + # prompt for domain + $newDomain = Read-Host -Prompt "Enter domain ($domain)" + if($newDomain -ne ''){ $domain = $newDomain } + + # prompt for username + $newUsername = Read-Host -Prompt "Enter username ($username)" + if($newUsername -ne ''){ $username = $newUsername } + } + + # prompt for password + __writeLog "Prompting for Password" + if(!$password){ + $secureString = Read-Host -Prompt "Enter password for $domain\$username at $vip" -AsSecureString + $passwd = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $secureString )) + }else{ + $passwd = $password + } + $opwd = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($passwd)) + + $pwlist = Get-Content -Path $pwfile -ErrorAction SilentlyContinue + $updatedContent = '' + $foundPwd = $false + foreach($pwitem in $pwlist){ + $v, $d, $u, $cpwd = $pwitem.split(":", 4) + # update existing + if($v -eq $vip -and $d -eq $domain -and $u -eq $username){ + $foundPwd = $true + $updatedContent += "{0}:{1}:{2}:{3}`n" -f $vip, $domain, $username, $opwd + # other existing records + }else{ + if($pwitem -ne ''){ + $updatedContent += "{0}`n" -f $pwitem + } + } + } + # add new + if(!$foundPwd){ + $updatedContent += "{0}:{1}:{2}:{3}`n" -f $vip, $domain, $username, $opwd + } + + $updatedContent | out-file -FilePath $pwfile + Write-Host "Password stored!" -ForegroundColor Green +} + + +function Set-CohesityAPIPassword($vip, $username, $domain='local', $passwd=$null){ + # prompt for vip + if(-not $vip){ + __writeLog "Prompting for VIP" + Write-Host 'VIP: ' -foregroundcolor green -nonewline + $vip = Read-Host + if(-not $vip){Write-Host 'vip is required' -foregroundcolor red; break} + } + # prompt for username + if(-not $username){ + __writeLog "Prompting for Username" + Write-Host 'Username: ' -foregroundcolor green -nonewline + $username = Read-Host + if(-not $username){Write-Host 'username is required' -foregroundcolor red; break} + } + # parse domain\username or username@domain + if($username.Contains('\')){ + $domain, $username = $username.Split('\') + } + if($username.Contains('@')){ + $username, $domain = $username.Split('@') + } + $keyName = "$vip`:$domain`:$username" + if(!$passwd){ + __writeLog "Prompting for Password" + $secureString = Read-Host -Prompt "Enter password for $username at $vip" -AsSecureString + $passwd = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $secureString )) + } + if($PSVersionTable.Platform -eq 'Unix'){ + # Unix + $keyFile = "$CONFDIR/$keyName" + $key = New-AesKey + $key | Out-File $keyFile + Protect-CohesityAPIPassword $key $passwd | Out-File $keyFile -Append + }else{ + # Windows + $securePassword = ConvertTo-SecureString -String $passwd -AsPlainText -Force + $encryptedPasswordText = $securePassword | ConvertFrom-SecureString + if(!(Test-Path $registryPath)){ + New-Item -Path $registryPath -Force | Out-Null + } + Set-ItemProperty -Path "$registryPath" -Name "$keyName" -Value "$encryptedPasswordText" + } +} + + +# security functions ============================================================================== + +function New-AesManagedObject($key, $IV){ + $aesManaged = New-Object "System.Security.Cryptography.AesManaged" + $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC + $aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros + $aesManaged.BlockSize = 128 + $aesManaged.KeySize = 256 + if($IV){ + if($IV.getType().Name -eq "String"){ + $aesManaged.IV = [System.Convert]::FromBase64String($IV) + }else{ + $aesManaged.IV = $IV + } + } + if($key){ + if($key.getType().Name -eq "String") { + $aesManaged.Key = [System.Convert]::FromBase64String($key) + }else{ + $aesManaged.Key = $key + } + } + $aesManaged +} + +function New-AesKey() { + $aesManaged = New-AesManagedObject + $aesManaged.GenerateKey() + [System.Convert]::ToBase64String($aesManaged.Key) +} + +function Protect-CohesityAPIPassword($key, $unencryptedString) { + $bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString) + $aesManaged = New-AesManagedObject $key + $encryptor = $aesManaged.CreateEncryptor() + $encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length); + [byte[]] $fullData = $aesManaged.IV + $encryptedData + $aesManaged.Dispose() + [System.Convert]::ToBase64String($fullData) +} + +function Unprotect-CohesityAPIPassword($key, $encryptedStringWithIV) { + $bytes = [System.Convert]::FromBase64String($encryptedStringWithIV) + $IV = $bytes[0..15] + $aesManaged = New-AesManagedObject $key $IV + $decryptor = $aesManaged.CreateDecryptor(); + $unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16); + $aesManaged.Dispose() + [System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0) +} + +# developer tools ================================================================================= + +function saveJson($object, $jsonFile = './debug.json'){ + $object | ConvertTo-Json -Depth 99 | out-file -FilePath $jsonFile +} + +function loadJson($jsonFile = './debug.json'){ + return Get-Content $jsonFile | ConvertFrom-Json +} + +function json2code($json = '', $jsonFile = '', $psFile = 'myObject.ps1'){ + + if($jsonFile -ne ''){ + $json = (Get-Content $jsonFile) -join "`n" + } + + $json = $json | ConvertFrom-Json | ConvertTo-Json -Depth 99 + + $pscode = '' + foreach ($line in $json.split("`n")) { + $line = $line.TrimEnd() + # preserve end of line character + $finalEntry = $true + if ($line[-1] -eq ',') { + $finalEntry = $false + $line = $line -replace ".$" + } + + # key value delimiter : + $key, $value = $line.split(':', 2) + + # line is braces only + $key = $key.Replace('{', '@{').Replace('[','@(').Replace(']', ')') + + if ($value) { + $value = $value.trim() + + # value is quoted text + if ($value[0] -eq '"') { + $line = "$key = $value" + } + + # value is opening { brace + elseif ('{' -eq $value) { + $value = $value.Replace('{', '@{') + $line = "$key = $value" + } + + # value is opening [ list + elseif ('[' -eq $value) { + $value = $value.Replace('[', '@(') + $line = "$key = $value" + } + + # empty braces + elseif ('{}' -eq $value) { + $value = '@{}' + $line = "$key = $value" + } + + # empty list + elseif ('[]' -eq $value) { + $value = '@()' + $line = "$key = $value" + } + + # value is opening ( list + elseif ('[' -eq $value) { + $value = $value.Replace('[', '@(') + $line = "$key = $value" + } + + # value is a boolean + elseif ($value -eq 'true') { + $line = "$key = " + '$true' + } + + elseif ($value -eq 'false') { + $line = "$key = " + '$false' + } + + # null + elseif ($value -eq 'null') { + $line = "$key = " + '$null' + } + else { + + # value is numeric + if ($value -as [long] -or $value -eq '0') { + $line = "$($key) = $value" + } + else { + + # delimeter : was inside of quotes + $line = "$($key):$($value)" + } + } + } + else { + + # was no value on this line + $line = $key + } + + # replace end of line character ; + if (! $finalEntry) { + $line = "$line;" + } + + $pscode += "$line`n" + } + + $pscode = '$myObject = ' + $pscode + + $pscode | out-file $psFile + return $pscode +} + +# add a property +function setApiProperty{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $True)][string]$name, + [Parameter(Mandatory = $True)][System.Object]$value, + [Parameter(Mandatory = $True, ValueFromPipeline = $True)][System.Object]$object + ) + if(! $object.PSObject.Properties[$name]){ + $object | Add-Member -MemberType NoteProperty -Name $name -Value $value + }else{ + $object.$name = $value + } +} + +# delete a propery +function delApiProperty{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $True)][string]$name, + [Parameter(Mandatory = $True, ValueFromPipeline = $True)][System.Object]$object + ) + $object.PSObject.Members.Remove($name) +} + +# show properties of an object +function showProps{ + param ( + [Parameter(Mandatory = $True)]$obj, + [Parameter()]$parent = 'myobject', + [Parameter()]$search = $null + ) + if($obj.getType().Name -eq 'String' -or $obj.getType().Name -eq 'Int64'){ + if($null -ne $search){ + if($parent.ToLower().Contains($search) -or ($obj.getType().Name -eq 'String' -and $obj.ToLower().Contains($search))){ + "$parent = $obj" + } + }else{ + "$parent = $obj" + } + + }else{ + foreach($prop in $obj.PSObject.Properties | Sort-Object -Property Name){ + if($($prop.Value.GetType().Name) -eq 'PSCustomObject'){ + $thisObj = $prop.Value + showProps $thisObj "$parent.$($prop.Name)" $search + }elseif($($prop.Value.GetType().Name) -eq 'Object[]'){ + $thisObj = $prop.Value + $x = 0 + foreach($item in $thisObj){ + showProps $thisObj[$x] "$parent.$($prop.Name)[$x]" $search + $x += 1 + } + }else{ + if($null -ne $search){ + if($prop.Name.ToLower().Contains($search.ToLower()) -or ($prop.Value.getType().Name -eq 'String' -and $prop.Value.ToLower().Contains($search.ToLower()))){ + "$parent.$($prop.Name) = $($prop.Value)" + } + }else{ + "$parent.$($prop.Name) = $($prop.Value)" + } + } + } + } +} + +# convert syntax to python +function py($p){ + $py = $p.replace("$","").replace("].","]['").replace(".","']['") + if($py[-1] -ne ']'){ + $py += "']" + } + $py +} + + +# self updater +function cohesityAPIversion([switch]$update){ + if($update){ + $repoURL = 'https://raw.githubusercontent.com/bseltz-cohesity/scripts/master/powershell' + (Invoke-WebRequest -Uri "$repoURL/cohesity-api/cohesity-api.ps1").content | Out-File -Force cohesity-api.ps1; (Get-Content cohesity-api.ps1) | Set-Content cohesity-api.ps1 + Write-Host "Cohesity-API version updated! Please restart PowerShell" + }else{ + Write-Host "Cohesity-API version $versionCohesityAPI" -ForegroundColor Green + } +} + + +# paged view list +function getViews([switch]$includeInactive){ + $myViews = @() + $views = $null + while(! $views){ + if($includeInactive){ + $views = api get views?includeInactive=true + }else{ + $views = api get views + } + } + $myViews += $views.views + $lastResult = $views.lastResult + while(! $lastResult){ + $lastViewId = $views.views[-1].viewId + $views = $null + while(! $views){ + if($includeInactive){ + $views = api get "views?maxViewId=$lastViewId&includeInactive=true" + }else{ + $views = api get views?maxViewId=$lastViewId + } + } + $lastResult = $views.lastResult + $myViews += $views.views + } + return $myViews +} + +# old version history +# . . . . . . . . . . . . . . . . . . . . . . . . +# 0.06 - Consolidated Windows and Unix versions - June 2018 +# 0.07 - Added saveJson, loadJson and json2code utility functions - Feb 2019 +# 0.08 - added -prompt to prompt for password rather than save - Mar 2019 +# 0.09 - added setApiProperty / delApiProperty - Apr 2019 +# 0.10 - added $REPORTAPIERRORS constant - Apr 2019 +# 0.11 - added storePassword function and username parsing - Aug 2019 +# 0.12 - added -password to apiauth function - Oct 2019 +# 0.13 - added showProps function - Nov 2019 +# 0.14 - added storePasswordFromInput function - Dec 2019 +# 0.15 - added support for PS Core on Windows - Dec 2019 +# 0.16 - added ServicePoint connection workaround - Jan 2020 +# 0.17 - fixed json2code line endings on Windows - Jan 2020 +# 0.18 - added REINVOKE - Jan 2020 +# 0.19 - fixed password encryption for PowerShell 7.0 - Mar 2020 +# 0.20 - refactored, added apipwd, added helios access - Mar 2020 +# 0.21 - helios changes - Mar 2020 +# 0.22 - added password file storage - Apr 2020 +# 0.23 - added self updater - Apr 2020 +# 0.24 - added delete with body - Apr 2020 +# 0.25 - added paged view list - Apr 2020 +# 0.26 - added support for tenants - May 2020 +# 0.27 - added support for Iris API Key - May 2020 +# 0.28 - added reprompt for password, debug log - June 2020 +# 0.29 - update storePasswordInFile - June 2020 +# 2020.06.04 - updated version numbering - June 2020 +# 2020.06.16 - improved REINVOKE - June 2020 +# 2020-06.25 - added API v2 support (-version 2) or (-v2) +# 2020.07.08 - removed timout +# 2020.07.20 - fixed dateToUsecs for international date formats +# 2020.07.30 - quiet ssl handler +# 2020.08.08 - fixed timezone issue +# 2020.10.02 - set PROMPTFORPASSWORDCHANGE to false +# 2020.10.05 - retired REINVOKE +# 2020.10.06 - exit script when attempting unauthenticated api call +# 2020.10.13 - fixed timeAgo function for i14n +# . . . . . . . . . . . . . . . . . . . . . . . . + diff --git a/_NDGOV_CS/ITD.Cohesity/azure-pipelines.yml b/_NDGOV_CS/ITD.Cohesity/azure-pipelines.yml new file mode 100644 index 0000000..c761363 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/azure-pipelines.yml @@ -0,0 +1,32 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: ubuntu-latest + +variables: + fName: 'Cohesity-Package' + pyEnv: $(System.DefaultWorkingDirectory)/python + +steps: +- task: ArchiveFiles@2 + inputs: + rootFolderOrFile: '$(System.DefaultWorkingDirectory)' + includeRootFolder: false + archiveType: 'zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip' + replaceExistingArchive: true +- task: rename@0 + inputs: + Command: 'rename' + SourceFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip' + NewName: '$(fName).zip' + +- upload: $(Build.ArtifactStagingDirectory)/$(fName).zip + displayName: 'Upload Package' + artifact: drop diff --git a/_NDGOV_CS/ITD.Cohesity/beta/getSQLSourceErrorMessages.py b/_NDGOV_CS/ITD.Cohesity/beta/getSQLSourceErrorMessages.py new file mode 100644 index 0000000..32afb27 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/getSQLSourceErrorMessages.py @@ -0,0 +1,109 @@ +import json +import sys +import certifi +import urllib3 +import time +import pymsteams + +from datetime import date, timedelta + +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import serviceNowAPI as serviceNow + +debug=0 +failureLimit=1 +iteration=0 +errorCount = 0 + +itdTeamsMessage = pymsteams.connectorcard("https://ndgov.webhook.office.com/webhookb2/aad89030-8f69-4a4d-a853-c882cbb01a10@2dea0464-da51-4a88-bae2-b3db94bc0c54/IncomingWebhook/d3c07921419c4920810d0c32558c05e3/edcc1502-1ff0-4c3e-9fe2-1ce3f9f7981a") + +try: + # Create the API object for Cohesity + mdn = cohesity.API('itdmdndpc01.nd.gov') + mdnToken = mdn.GetAuthToken() + mdn.UpdateHeaders(mdnToken['accessToken']) + + # Create the API object for ServiceNow + ticketGenerator = serviceNow.API('northdakota.service-now.com') + + # Get all SQL resgistered SQL servers from Cohesity + vms = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo","?environments=kSQL") + + # Loop through all servers and check for health status issues + for vm in vms['rootNodes']: + for check in vm['registrationInfo']['registeredAppsInfo'][0]['hostSettingsCheckResults']: + if check['resultType'] == "kFail": + errorCount += 1 + # If/Else statement for Debug only, added iteration limit to prevent debug of multiple servers at once + if (debug == 1) and (iteration < failureLimit): + print("Hostname: " + vm['rootNode']['name']) + print("NodeID: " + str(vm['rootNode']['id'])) + print(check['resultType'] + ": " + check['userMessage']) + + iteration += 1 + + #Try to refresh the source to see if the error goes away + print("Attempting to refresh " + vm['rootNode']['name']) + mdn.RefreshSource(vm['rootNode']['id']) + time.sleep(15) + + #Pull the source registration information again and output + refreshedData = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo","?ids=" + str(vm['rootNode']['id'])) + + print("Refreshed Data") + #print(json.dumps(refreshedData,indent=4)) + + for refreshedVM in refreshedData['rootNodes']: + persistantError = 0 + for refreshedCheck in refreshedVM['registrationInfo']['registeredAppsInfo'][0]['hostSettingsCheckResults']: + if (refreshedCheck['resultType']=="kFail"): + print("Hostname: " + refreshedVM['rootNode']['name']) + print("NodeID: " + str(refreshedVM['rootNode']['id'])) + print(refreshedCheck['resultType'] + ": " + refreshedCheck['userMessage']) + persistantError += 1 + + # Open a service now ticket for any server that has a health issue + shortDesc = 'Cohesity: SQL Registration Error for ' + vm['rootNode']['name'] + description = 'Please assign this ticket to the SQL Admins to invesigate the following issue(s)\n' + check['userMessage'] + print("Opening Ticket") + + if persistantError == 0: + print("Refreshing the source " + vm['rootNode']['name'] + " resolved the registration error.") + + # Already in a 'failure' if statement, else is only for non-debug operation + elif (debug == 0): + #Try to refresh the source to see if the error goes away + mdn.RefreshSource(vm['rootNode']['id']) + time.sleep(15) + + #Pull the source registration information again and output + refreshedData = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo","?ids=" + str(vm['rootNode']['id'])) + + for refreshedVM in refreshedData['rootNodes']: + persistantError = 0 + for refreshedCheck in refreshedVM['registrationInfo']['registeredAppsInfo'][0]['hostSettingsCheckResults']: + if (refreshedCheck['resultType']=="kFail"): + # Open a service now ticket for any server that has a health issue + shortDesc = 'Cohesity: SQL Registration Error for ' + vm['rootNode']['name'] + description = 'Please assign this ticket to the SQL Admins to invesigate the following issue(s)\n' + check['userMessage'] + snResponse=ticketGenerator.submitTicket(shortDesc, description) + + itdTeamsMessage.text("SQL Registration error found. A ServiceNow ticket has been opened to investigate " + vm['rootNode']['name']) + itdTeamsMessage.send() + + # Ticket has been opened, break the loop to prevent opening multiple tickets for the same host. + break + + #End refreshed error/message checks loop + #End refreshed VM data loop + #End debug if/elif block + # End if failure message found + # End for loop of all error/warning message checks + # End for loop of all VMs + + itdTeamsMessage.text("Finished checking Cohesity SQL sources for registration errors, found: " + str(errorCount)) + itdTeamsMessage.send() + +except OSError as cohesityError: + print('Cohesity Error: ' + cohesityError) diff --git a/_NDGOV_CS/ITD.Cohesity/beta/regexTest.py b/_NDGOV_CS/ITD.Cohesity/beta/regexTest.py new file mode 100644 index 0000000..a44268b --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/regexTest.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +import sys,argparse,json,time,yaml +import re + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--server', '-s', type=str, action='store') + parser.add_argument('--vCenter', '-v', type=str, action='store') + return (parser.parse_args()) + +args = GetArgs() + +with open("./exemptions.yml", "r") as exemptionJobData: + try: + exemptionJobData = yaml.load(exemptionJobData, Loader=yaml.FullLoader) + except: + print("Unable to load exemptions file.") + + exemptServers = [] + + for i in exemptionJobData: + for e in exemptionJobData[i]['vms']: + exemptServers.append([exemptionJobData[i]['id'],e.lower()]) + + for entry in exemptServers: + parent = entry[0] + pattern = entry[1] + + if (parent == int(args.vCenter) and re.search(pattern, args.server)): + print("Found match with pattern: " + pattern) diff --git a/_NDGOV_CS/ITD.Cohesity/beta/systemHealth.py b/_NDGOV_CS/ITD.Cohesity/beta/systemHealth.py new file mode 100644 index 0000000..db49cc5 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/systemHealth.py @@ -0,0 +1,62 @@ +import sys + +# Import NDIT storage classes +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import serviceNowAPI as serviceNow + +def main(): + + # Instantiate the ServiceNow API + svcNowInterface = serviceNow.API('northdakota.service-now.com') + + # Instantiate Cohesity APIs + mdnCluster = cohesity.API('itdmdndpc01.nd.gov') + + clusters = [mdnCluster] + + replicationFailures = [] + sqlFailures = [] + backupFailures = [] + undetermined = [] + + for cluster in clusters: + cluster.Authenticate() + + alertID = 0 + openAlerts = cluster.GetFilteredRequest("/public/alerts","?alertStateList=kOpen&maxAlerts=1000") + if len(openAlerts) > 1: + for alert in openAlerts: + + if (alert['severity'] != "kInfo"): + # Open a unique ticket for every alert + + if (alert['alertCategory'] == "kRemoteReplication"): + replicationFailures.append(alert) + continue + + if (alert['alertCategory'] == "kBackupRestore"): + for item in alert['propertyList']: + if (item['value'] == "kSQL"): + sqlFailures.append(alert) + continue + + + shortDescription = "Backup Failure on " + str(cluster.GetClusterName()) + ": " + alert['alertDocument']['alertName'] + longDescription = alert['alertDocument']['alertCause'] + + print("Opening incident for Cohesity alert:" + str(alertID)) + print("\tShort Description: " + shortDescription) + print("\tLong Description: " + longDescription) + alertID += 1 + #End if alert['severity'] != kInfo + #End for alert in alerts + # End if len(openAlerts) > 1 + #End for cluster in clusters + + print("Total replication failures: " + str(len(replicationFailures))) + print("Total SQL Backup failures: " + str(len(sqlFailures))) +#End main() + +# Run the program +main() diff --git a/_NDGOV_CS/ITD.Cohesity/beta/temp-fixProtectionJobAttributes.py b/_NDGOV_CS/ITD.Cohesity/beta/temp-fixProtectionJobAttributes.py new file mode 100644 index 0000000..f0ea9f6 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/temp-fixProtectionJobAttributes.py @@ -0,0 +1,372 @@ +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +# Global variables that will be used across all functions +global tagid +tagid = None + +global tagName +tagName = None + +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--tag', '-t', type=str, action='store') + parser.add_argument('--group', '-g', type=str, action='store') + parser.add_argument('--action', '-a', type=str, action='store') + parser.add_argument('--list', '-l', type=str, action='store') + return (parser.parse_args()) + +def GetTagID(sources): + globalList = globals() + + for source in sources: + if globalList['tagid'] is None: + GetNode(sources) + +def GetNode(record): + globalList = globals() + + # A non 'node' element was found, check each child key to see if one contains 'kTag' + if "protectionSource" in record: + if "vmWareProtectionSource" in record['protectionSource']: + if record['protectionSource']['vmWareProtectionSource']['type'] == "kTag": + + # Tag elements have been found, look for the correct tag and assign the id to the global variable + if record['protectionSource']['vmWareProtectionSource']['name'] == globalList['tagName']: + + # Tag was found based on the name + globalList['tagid'] = record['protectionSource']['id'] + + # Recurse through all 'nodes' elements looking for kTag + if "nodes" in record: + for node in record['nodes']: + + # The tag hasn't been found, search the next record + if globalList['tagid'] is None: + GetNode(node) + + # The tag was found and the global id value was set, stop iterating. + else: + break + +def UpdateProtectionGroupExcludes(group, action): + globalList = globals() + isExcluded = False + tagArray = [] + + if "excludeVmTagIds" in group: + for index in group['excludeVmTagIds']: + for tag in index: + tagArray.append(tag) + if tag == globalList['tagid']: + isExcluded = True + + # Add the tag to the exclusion + if action == 'add': + if isExcluded == True: + print(globalList['tagName'] + " tag is already excluded for " + group['name']) + else: + print("Adding exclusion tag '" + globalList['tagName'] + "' to group " + group['name']) + tagArray.append(globalList['tagid']) + + # Remove the tag from the exclusion + elif action == 'remove': + if isExcluded == True: + print("Removing exclusion tag '" + globalList['tagName'] + "' from group " + group['name']) + tagArray.remove(globalList['tagid']) + else: + print(globalList['tagName'] + " tag is not excluded for " + group['name']) + + + return(tagArray) + +def UpdateProtectionGroupIncludes(group, action): + globalList = globals() + isIncluded = False + + tagArray = [] + + if "vmTagIds" in group: + for index in group['vmTagIds']: + for tag in index: + tagArray.append(tag) + if tag == globalList['tagid']: + isIncluded = True + + # Add the tag to the inclusion + if action == 'add': + if isIncluded == True: + print(globalList['tagName'] + " tag is already included for " + group['name']) + else: + print("Adding inclusion tag '" + globalList['tagName'] + "' to group " + group['name']) + tagArray.append(globalList['tagid']) + + # Remove the tag from the inclusion + elif action == 'remove': + if isIncluded == True: + print("Removing inclusion tag '" + globalList['tagName'] + "' from group " + group['name']) + tagArray.remove(globalList['tagid']) + else: + print(globalList['tagName'] + " tag is not included for " + group['name']) + + return(tagArray) + + +# Begin Main +globalList = globals() + +sourceFound = False +vCenter = None +vCenterID = None +tagIds = [] + +args = GetArgs() + +# Validate arguments & assign variables if necessary +if not args.cluster: + sys.exit("Error: Specify a Cohesity cluster fqdn with -c parameter.") +else: + globalList['tagName'] = args.tag + +if not args.vcenter: + sys.exit("Error: Specify a vCenter with -v parameter") + +if not args.tag: + sys.exit("Error: Specify a tag with the -t parameter.") + +if not args.action: + sys.exit("Error: Specify an action [add|remove] with -a parameter.") +elif args.action != 'add' and args.action != 'remove': + sys.exit("Error: Use only 'add' or 'remove' with -a parameter.") + +if not args.list: + sys.exit("Error: Specify a list [include|exclude] with -l parameter.") +elif args.list != 'exclude' and args.list != 'include': + sys.exit("Error: Use only 'include' or 'exclude' with -l parameter.") + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Locate the correct vCenter and capture the id, this will be useful to validate child objects +vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") +for source in vmSources: + if source['protectionSource']['name'] == args.vcenter: + sourceFound = True + vCenter = source + vCenterID = source['protectionSource']['id'] + break + +# The vCenter we are looking for was not in the list of kVMware environments, stop processing. +if sourceFound == False: + sys.exit("Error: " + args.vcenter + " is not registered to " + args.cluster) + +# Look up the tag id based on the tagName and set a global variable when found +# IMPROVEMENT TO GET AWAY FROM GLOBAL VAR +GetTagID(vCenter) + +if globalList['tagid'] is None: + sys.exit("Error: The tag '" + args.tag + "' does not exist in " + vCenter['protectionSource']['name']) + +if args.group: + # Replace '@' symbol with '%40' for URL encoding in the REST API + protectionGroup = args.group.replace("@","%40") + job = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + protectionGroup) + + print(json.dumps(job[0], indent=4)) + + if job[0]['parentSourceId'] != vCenterID: + sys.exit(job[0]['name'] + " does not belong to source " + vCenter['protectionSource']['name']) + else: + if (args.list == 'exclude'): + excludeTagIds = UpdateProtectionGroupExcludes(job[0], args.action) + if "excludeVmTagIds" in job[0]: + job[0]['excludeVmTagIds'][0] = excludeTagIds + else: + job[0].update({"excludeVmTagIds": [ excludeTagIds ]}) + else: + includeTagIds = UpdateProtectionGroupIncludes(job[0], args.action) + if "vmTagIds" in job[0]: + job[0]['vmTagIds'][0] = includeTagIds + else: + job[0].update({"includeVmTagIds": [ includeTagIds ]}) + + +# FIX the screw up + # Temp code to grab start time from previous runs + run = cluster.GetFilteredRequest("/public/protectionRuns","?numRuns=10&jobId=" + str(job[0]['id'])) + + try: + hour = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) + hour = time.strftime("%H", time.localtime(hour)) + minute = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) + minute = time.strftime("%M", time.localtime(minute)) + + hour = int(hour) + minute = int(minute) + + except: + hour = 21 + minute = 00 + + job[0]['startTime']['hour'] = hour + job[0]['startTime']['minute'] = minute + # EndTime + + # Temp code to build indexing + job[0].update({"indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }}) + + # Temp code to set SLA + job[0].update({"incrementalProtectionSlaTimeMins": 480}) + job[0].update({"fullProtectionSlaTimeMins": 480}) + + job[0].update({"abortInBlackoutPeriod": False}) + job[0].update({"quiesce": False}) + job[0].update({"qosType": "kBackupHDD"}) + job[0].update({"environmentParameters":{ + "vmwareParameters": { + "fallbackToCrashConsistent": False, + "skipPhysicalRdmDisks": False + } + }}) + job[0].update({"cloudParameters":{"failoverToCloud": False}}) + job[0].update({"leverageStorageSnapshots": False}) + job[0].update({"leverageStorageSnapshotsForHyperFlex": False}) + job[0].update({"description": ""}) + +# End Fix + + + # Take acion on group(s) + resp = cluster.UpdateVMProtectionJob(job[0]) + print(resp.content) + +else: + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + + for job in uniqueJobs: + if "isPaused" in job: + if job['isPaused']: + continue + # If the job is marked for deletion, skip + if 'isDeleted' in job: + continue + + # If the job does not belong to this vCetner, skip + if job['parentSourceId'] != vCenterID: + continue + + else: + if (args.list == 'exclude'): + excludeTagIds = UpdateProtectionGroupExcludes(job, args.action) + + if "excludeVmTagIds" in job: + job['excludeVmTagIds'][0] = excludeTagIds + else: + job.update({"excludeVmTagIds": [ excludeTagIds ]}) + + else: + includeTagIds = UpdateProtectionGroupIncludes(job, args.action) + + if "vmTagIds" in job: + job['vmTagIds'][0] = includeTagIds + else: + job.update({"includeVmTagIds": [ includeTagIds ]}) + +# FIX the screw up + # Temp code to grab start time from previous runs + run = cluster.GetFilteredRequest("/public/protectionRuns","?numRuns=10&jobId=" + str(job['id'])) + + try: + hour = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) + hour = time.strftime("%H", time.localtime(hour)) + minute = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) + minute = time.strftime("%M", time.localtime(minute)) + + hour = int(hour) + minute = int(minute) + + except: + hour = 21 + minute = 00 + + job['startTime']['hour'] = hour + job['startTime']['minute'] = minute + # EndTime + + # Temp code to build indexing + job.update({"indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }}) + + # Temp code to set SLA + job.update({"incrementalProtectionSlaTimeMins": 480}) + job.update({"fullProtectionSlaTimeMins": 480}) + + job.update({"abortInBlackoutPeriod": False}) + job.update({"quiesce": False}) + job.update({"qosType": "kBackupHDD"}) + job.update({"environmentParameters":{ + "vmwareParameters": { + "fallbackToCrashConsistent": False, + "skipPhysicalRdmDisks": False + } + }}) + job.update({"cloudParameters":{"failoverToCloud": False}}) + job.update({"leverageStorageSnapshots": False}) + job.update({"leverageStorageSnapshotsForHyperFlex": False}) + job.update({"description": ""}) + + + # Take acion on group(s) + print("Updating: " + job['name']) + resp = cluster.UpdateVMProtectionJob(job) + print(resp.content) diff --git a/_NDGOV_CS/ITD.Cohesity/beta/template.py b/_NDGOV_CS/ITD.Cohesity/beta/template.py new file mode 100644 index 0000000..732bcda --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/template.py @@ -0,0 +1,89 @@ +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--job', '-j', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("Set OS environment variables ITD_SHAREPOINT_PASS and ITD_SHAREPOINT_USER") + print("\nExample:") + print(r"$ export COHESITY_USER=\"NDGOV\jDoe\"") + print("$ export COHESITY_PASS=\"1Lik3Jane\"") + print("\n python3 -c cluster1.domain.tld [ -v vCenter.domain.tld ] [ -j protectionJobName ]") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v FQDN of vCenter Server, used in conjuntion with -t kVMware ") + print("\t -j Cohesity job name") + print("\t -h Prints this help message") + +args = GetArgs() + +if args.help: + PrintHelp() + +if not args.cluster: + sys.exit("Error: Specify Cohesity cluster fqdn with -c parameter.") +else: + cluster = cohesity.API(args.cluster) + authToken = cluster.GetAuthToken() + cluster.UpdateHeaders(authToken['accessToken']) + +if args.vcenter: + vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") + + for source in vmSources: + if source['protectionSource']['name'] == args.vcenter: + vCenter = source + vCenterID = source['protectionSource']['id'] + break + + if args.job: + # Get the details of a single job + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + args.job) + else: + # Get the details of all jobs under a vCenter + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") + + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + +# Do stuff with the JSON data +# Example: + if args.pause: + pausedJobs = [] + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + print("not vcenter") + continue + + elif "isDeleted" in job: + continue + + elif "isPaused" in job: + if job['isPaused']: + pausedJobs.append(job) + continue + + print("Pausing: " + job['name']) + resp = cluster.PauseJob(job['id']) + + print("The following jobs were previously paused before this operation.") + for pJob in pausedJobs: + print(pJob['name']) + + if args.resume: + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + continue + + elif "isDeleted" in job: + continue + + print("Resuming: " + job['name']) + resp = cluster.ResumeJob(job['id']) diff --git a/_NDGOV_CS/ITD.Cohesity/beta/updateSQLProtectionJob_policy.py b/_NDGOV_CS/ITD.Cohesity/beta/updateSQLProtectionJob_policy.py new file mode 100644 index 0000000..df6194b --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/beta/updateSQLProtectionJob_policy.py @@ -0,0 +1,21 @@ +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +mdn = cohesity.API('itdmdndpc01.nd.gov') +mdnToken = mdn.GetAuthToken() +mdn.UpdateHeaders(mdnToken['accessToken']) + +# Block Update all SQL jobs with new SQL policy +sqlPolicyName = mdn.GetFilteredRequest("/public/protectionPolicies", "?names=ITD-SQL") + +sqlProtectionJobs = mdn.GetFilteredRequest("/public/protectionJobs", "?environments=kSQL") +uniqueJobs = {job['id'] : job for job in sqlProtectionJobs}.values() + +isPaused=bool('false') + +for job in uniqueJobs: + resp = mdn.UpdateProtectionJob(job['sourceIds'],job['parentSourceId'], job['name'], sqlPolicyName[0]['id'], job['viewBoxId'], job['id'], isPaused) + print(resp.content) +#End SQL Policy Update Block diff --git a/_NDGOV_CS/ITD.Cohesity/cancelJobs.py b/_NDGOV_CS/ITD.Cohesity/cancelJobs.py new file mode 100644 index 0000000..35623f0 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/cancelJobs.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 cancelJobs.py -c cluster1.domain.tld" ) + print("\t -c FQDN of Cohesity cluster address") + print("\t -h Prints this help message") + + +args = GetArgs() + +if arg.help: + PrintHelp() + exit(1) + +# Validate arguments & assign variables if necessary +if not args.cluster: + sys.exit("Error: Specify a Cohesity cluster fqdn with -c parameter.") + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") +uniqueJobs = {job['id'] : job for job in vmJobs}.values() + +# Non Running states +finStates = ['kCanceled', 'kSuccess', 'kFailure', 'kWarning'] + +for job in uniqueJobs: + if 'isDeleted' in job: + continue + if 'isPaused' in job: + continue + + # Get running protections per vmware protection job id, most recent is returned + run = cluster.GetFilteredRequest("/public/protectionRuns","?numRuns=10&jobId=" + str(job['id'])) + + if run[0]['backupRun']['status'] not in finStates: + # Cancel the running protection job + resp = cluster.CancelJob(job['id'],run[0]['backupRun']['jobRunId']) + + # Print the response + print(resp.content) + diff --git a/_NDGOV_CS/ITD.Cohesity/classes/automationsAPI.py b/_NDGOV_CS/ITD.Cohesity/classes/automationsAPI.py new file mode 100644 index 0000000..3f1de0a --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/classes/automationsAPI.py @@ -0,0 +1,7 @@ +import requests + +def send_automation(_data: dict): + _url = 'http://itdnettools.nd.gov/services/automation-tracking.py' + _r = requests.post(_url, json=_data) + return _r.text + diff --git a/_NDGOV_CS/ITD.Cohesity/classes/cohesityAPI.py b/_NDGOV_CS/ITD.Cohesity/classes/cohesityAPI.py new file mode 100644 index 0000000..5827f8a --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/classes/cohesityAPI.py @@ -0,0 +1,792 @@ +import json +import random +import requests +import urllib3 +import certifi +import os +import pytz +from datetime import datetime, timedelta, time + +class API(object): + def __init__(self, server): + + if not ((os.environ.get('COHESITY_USER')) and (os.environ.get('COHESITY_PASS'))): + print("\n*** Environment Variables are not set for authentication! ***") + exit() + # Get the authorization bearer token + self.user = os.environ['COHESITY_USER'] + self.pwd = os.environ['COHESITY_PASS'] + if self.user == "svcitdchstyauto": + self.domain = "local" + else: + self.domain = "nd.gov" + self.server = server + self.base_url = ('https://{}/irisservices/api/v1').format(self.server) + self.headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + + def GetClusterName(self): + return self.server + + ###################################################### Depricated Methods ################################################# + def GetAuthToken(self): + apiCall = "/public/accessTokens" + payload = { + "username": self.user, + "password": self.pwd, + "domain": self.domain + } + encoded_payload = json.dumps(payload) + token = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload, verify=True) + if 'locked' in token.text: + print("Account {} is locked".format(self.user)) + exit(1) + if 'expired' in token.text: + print("Password for local account {} has expired".format(self.user)) + exit(1) + return(self.FormatData(token)) + + ########################################################################################################################### + + # Methods under maintenance + def FormatData(self, response): + jsonData = json.loads(response.text) + return (jsonData) + + def GetClusterName(self): + return(self.server) + + def Authenticate(self): + apiCall = "/public/accessTokens" + payload = { + "username": self.user, + "password": self.pwd, + "domain": self.domain + } + encoded_payload = json.dumps(payload) + authResponse = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload, verify=True) + token = self.FormatData(authResponse) + + if (token['accessToken']): + self.headers.update({'Authorization': 'Bearer ' + token['accessToken']}) + return() + else: + print("ERROR: Unable to authenticate to " + self.server) + + def UpdateHeaders(self, token): + self.headers.update({'Authorization': 'Bearer ' + token}) + + def GetRelativeTimestamp(self, d, h, m, s): + + # Timezone + tz = pytz.timezone("America/Chicago") + + # Current date + date = datetime.now(tz).date() + + # Convert to yesterday + start_date = date + timedelta(days=d) + + # Set time to 1700 + start_time = datetime( + year = start_date.year, + month = start_date.month, + day = start_date.day, + hour = h, + minute = m, + second = s + ) + + # Add timezone info to the start time + start_time = tz.localize(start_time) + + # Convert to UTC + start_utc_time = start_time.astimezone(pytz.utc) + + # Convert to unix epoch microseconds + start_epoch_ms = int(start_utc_time.timestamp() * 1000000) + + return(start_epoch_ms) + + def GetRandomStartTime(self): + hours = [17, 18, 19, 20, 21, 22, 23, 00, 1, 2, 3, 4, 5, 6] + min = [0, 15, 30, 45] + rHour = random.choice(hours) + rMin = random.choice(min) + sTime=[rHour,rMin] + + return sTime + +#################### DELETE Methods #################### + def DeleteJob(self, url): + apiCall = url + payload = { + "deleteSnapshots": True + } + encoded_payload = json.dumps(payload) + data = requests.delete(self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return(data) + + + +#################### SET Methods ####################### + + def ResolveAlert(self, alert_id, snow_id): + apiCall = "/public/alertResolutions" + payload = { + "alertIdList": [ + alert_id + ], + "resolutionDetails": { + "resolutionDetails":"See ServiceNow", + "resolutionSummary": snow_id + } + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + + return(self.GetRequest(apiCall)) + +#################### GET Methods ####################### + + def GetRequest(self, url): + apiCall = url + payload = {} + encoded_payload = json.dumps(payload) + data = requests.request("GET", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return(self.FormatData(data)) + + def GetRequestV2(self, url): + base_url = ('https://{}/v2').format(self.server) + apiCall = url + payload = {} + encoded_payload = json.dumps(payload) + data = requests.request("GET", base_url + apiCall, headers=self.headers, data=encoded_payload) + return(self.FormatData(data)) + + def GetFilteredRequest(self, url, filters): + apiCall = url + filters + payload = {} + encoded_payload = json.dumps(payload) + data = requests.request("GET", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return(self.FormatData(data)) + + def GetPhysicalsources(self): + apiCall = "/public/protectionSources/registrationInfo?isDeleted=False&environments=kPhysical" + return(self.GetRequest(apiCall)) + + def GetSQLsources(self): + apiCall = "/public/protectionSources/registrationInfo?isDeleted=False&environments=kSQL" + return(self.GetRequest(apiCall)) + + def GetSQLjobs(self): + apiCall = "/public/protectionJobs/?isDeleted=False&environments=kSQL" + return(self.FormatData(self.GetRequest(apiCall))) + + def GetVMsources(self): + apiCall = "/public/protectionSources?environments=kVMware" + return(self.GetRequest(apiCall)) + + def GetVMjobs(self): + apiCall = "/public/protectionJobs?environments=kVMware" + return(self.GetRequest(apiCall)) + + def GetDiskAlerts(self, startTime): + apiCall = "/public/alerts?alertStateList=kOpen&alertCategoryList=kDisk&startDateUsecs=" + str(startTime) + return(self.GetRequest(apiCall)) + + def GetProtectedVMobjects(self, hypervisorID): + apiCall = "/public/protectionSources/protectedObjects?environment=kVMware&id=" + str(hypervisorID) + return(self.GetRequest(apiCall)) + + def GetProtectionPolicyByName(self, policyName): + apiCall = "/public/protectionPolicies/?name=" + policyName + return(self.GetRequest(apiCall)) + + def GetVMObjects(self, hypervisorID): + apiCall = "/public/protectionSources/virtualMachines?vCenterId=" + str(hypervisorID) + return(self.GetRequest(apiCall)) + + def GetAZsources(self): + apiCall = "/public/protectionSources?environments=kAzure" + return(self.GetRequest(apiCall)) + + def GetAZNativeJobs(self): + apiCall = "/public/protectionJobs?environments=kAzureNative" + return(self.GetRequest(apiCall)) + + def GetAZObjects(self, hypervisorID): + apiCall = "/public/protectionSources?environments=kAzure&id=" + str(hypervisorID) + data = self.GetRequest(apiCall) + azureVMs = [] + for node in data[0]['nodes']: + if 'nodes' in node: + for subNode in node['nodes']: + if 'protectionSource' in subNode: + if 'azureProtectionSource' in subNode['protectionSource']: + if "type" in subNode['protectionSource']['azureProtectionSource']: + if subNode['protectionSource']['azureProtectionSource']['type'] == 'kVirtualMachine': + azureVMs.append(subNode['protectionSource']) + return(azureVMs) + + def GetProtectedAZobjects(self, hypervisorID): + apiCall = "/public/protectionSources/protectedObjects?environment=kAzure&id=" + str(hypervisorID) + return(self.GetRequest(apiCall)) + + def GetPhysicalJobs(self): + apiCalll = "/public/protectionJobs?isDeleted=False&environments=kPhysicalFiles" + return(self.FormatData(self.GetRequest(apiCall))) + + def GetProtectionSourceId(self, hostname): + sourceRegistered = False + hostname = hostname.lower() + sources = self.GetFilteredRequest("/public/protectionSources/registrationInfo", "?environments=kPhysical") + + for source in sources['rootNodes']: + if (source['rootNode']['name']).lower() == hostname: + sourceId = source['rootNode']['id'] + sourceRegistered = True + break + if sourceRegistered: + return(sourceId) + else: + sys.exit("Source not registered") + + def GetVcenterTagId(self, vCenterId, tagName): + tagFound=0 + for record in vCenterId[0]['nodes'][0]['nodes']: + if "protectionSource" in record: + if "name" in record['protectionSource']: + # Check if tagName matches AppName + if record['protectionSource']['name'] == "AppName": + for tagRecord in record['nodes']: + if tagRecord['protectionSource']['name'] == tagName and tagRecord['protectionSource']['vmWareProtectionSource']['type'] == "kTag": + tagId = tagRecord['protectionSource']['id'] + tagFound = 1 + break + + # Check if tagName matches DTAP (Development, Test, Acceptable, Production) + if record['protectionSource']['name'] == "DTAP": + for tagRecord in record['nodes']: + if tagRecord['protectionSource']['name'] == tagName and tagRecord['protectionSource']['vmWareProtectionSource']['type'] == "kTag": + tagId = tagRecord['protectionSource']['id'] + tagFound = 1 + break + if tagFound == 1: + break + if tagFound == 1: + return tagId + else: + return None + + def GetAzureTagId(self, azSubId, tagName): + tagFound = 0 + for record in azSubId[0]['nodes']: + if "protectionSource" in record: + if "name" in record['protectionSource']: + if record['protectionSource']['name'] == "ApplicationName#~#" + tagName: + if record['protectionSource']['azureProtectionSource']['type'] == "kTag": + tagId = record['protectionSource']['id'] + tagFound = 1 + break + if tagFound == 1: + break + if tagFound == 1: + return tagId + else: + return None + + def GetProtectionJobByHost(self, hostname): + jobFound = False + jobs = self.GetFilteredRequest("/public/protectionJobs", "?isDeleted=False&environments=kPhysicalFiles,kSQL") + sourceId = self.GetProtectionSourceId(hostname) + for job in jobs: + for source in job['sourceIds']: + if source == sourceId: + jobName = job['name'] + jobFound = True + break + + # Job was found break out of the jobs loop + if jobFound: + break + + if jobFound: + return(job) + else: + return(-1) + +################### Registration Methods ################## + + def RemoveProtectionSource(self, sourceId): + apiCall = "/public/protectionSources/" + str(sourceId) + response = requests.request("DELETE", self.base_url + apiCall, headers=self.headers) + return(response) + + def RegisterPhysical(self, hostName): + apiCall = "/public/protectionSources/register" + payload = { + "environment": "kPhysical", + "physicalType": "kHost", + "forceRegister" : True, + # The API will error if hostType is not specified; however during the registration process Cohesity will register + # the correct type even if the incorrect type was given in the payload. + "hostType": "kWindows", + "endpoint": hostName + } + + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return(self.FormatData(response)) + + def RegisterSQL(self, sourceID): + apiCall = "/public/protectionSources/applicationServers" + payload = { + "applications": [ + "kSQL" + ], + "hasPersistentAgent": bool("true"), + "protectionSourceId": sourceID + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (self.FormatData(response)) + + def RefreshSource(self, sourceID): + apiCall = "/public/protectionSources/refresh/" + str(sourceID) + payload = {} + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers) + return + +################ Protection Job Methods ####################### + + def PauseJob(self, jobId): + apiCall = "/public/protectionJobState/" + str(jobId) + payload = { + "pause": True, + "pauseReason": 0 + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def ResumeJob(self, jobId): + apiCall = "/public/protectionJobState/" + str(jobId) + payload = { + "pause": False, + "pauseReason": 0 + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CancelJob(self, jobId, runId): + apiCall = "/public/protectionRuns/cancel/" + str(jobId) + payload = { + "jobRunId": runId + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def UpdateVMProtectionJob(self, job): + apiCall = "/public/protectionJobs/" + str(job['id']) + payload = job + encoded_payload = json.dumps(payload) + response = requests.request("PUT", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def UpdateProtectionJob(self, job): + apiCall = "/public/protectionJobs/" + str(job['id']) + payload = job + encoded_payload = json.dumps(payload) + response = requests.request("PUT", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def UpdateAZprotectionJob(self, job): + base_url = ('https://{}/v2').format(self.server) + apiCall = "/data-protect/protection-groups/7780085755317378:1694019083558:" + str(job['id']) + payload = job + encoded_payload = json.dumps(payload) + response = requests.request("PUT", base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CreateVMProtectionJob(self, pgName, parentId, tagId, excludeTag, polId): + apiCall = "/public/protectionJobs/" + sTime=self.GetRandomStartTime() + payload = { + "name": pgName, + "description": "", + "environment": "kVMware", + # NDIT - Bronze Policy + "policyId": polId, + #"policyId": "4847477517838800:1610060943809:6402", + # Default Storage Domain + "viewBoxId": 198, + "parentSourceId": parentId, + "vmTagIds": [ + [ + tagId + ] + ], + "excludeVmTagIds": [ + [ + excludeTag + ] + ], + "startTime": { + "hour": sTime[0], + "minute": sTime[1] + }, + "timezone": "America/Chicago", + "incrementalProtectionSlaTimeMins": 480, + "fullProtectionSlaTimeMins": 480, + "priority": "kLow", + "indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }, + "abortInBlackoutPeriod": False, + "quiesce": False, + "qosType": "kBackupHDD", + "environmentParameters":{ + "vmwareParameters":{ + "fallbackToCrashConsistent": False, + "skipPhysicalRdmDisks": False + } + }, + "cloudParameters": { + "failoverToCloud": False + }, + "leverageStorageSnapshots": False, + "leverageStorageSnapshotsForHyperFlex": False, + "isPaused": False + } + + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CreateAZSQLProtectionJob(self, srcId, pgName): + apiCall = "/public/protectionJobs/" + payload = { + "name": pgName, + + # NDIT - Bronze Policy + "policyId": "7780085755317378:1694019083558:289", + + # Default Storage Domain + "viewBoxId": 36, + + # SQL Server kRootContainer + "parentSourceId": 6, + + "sourceIds": [ + srcId + ], + + "startTime": { + "hour": 22, + "minute": 00 + }, + + "timezone": "America/Chicago", + + "fullProtectionSlaTimeMins": 480, + "incrementalProtectionSlaTimeMins": 480, + "priority": "kLow", + "LeverageSanTransport": False, + + # Default Indexing Policy + "indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }, + + "environment": "kSQL", + "environmentParameters": { + "sqlParameters": { + "userDatabasePreference": "kBackupAllDatabases", + "backupSystemDatabases": bool('true'), + "aagPreferenceFromSqlServer": bool('true'), + "backupType": "kSqlVSSVolume", + "backupVolumesOnly": bool('true') + } + + }, + + "abortInBlackoutPeriod": False, + "qosType": "kBackupHDD", + "description": "", + "isPaused": False + } + + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CreateAZProtectionJob(self, pgName, parentId, tagId): + base_url = ('https://{}/v2').format(self.server) + apiCall = "/data-protect/protection-groups" + payload = { + "name": pgName, + "description": "", + # NDIT - Bronze Policy + #"policyId": "5033496487614715:1619543500905:271778", + "policyId": "7780085755317378:1694019083558:2291", + # Default Storage Domain + "storageDomainId": 36, + "startTime": { + "hour": 19, + "minute": 00, + "timezone": "America/Chicago" + }, + "priority": "kLow", + "sla": [ + { + "backupRunType": "kIncremental", + "slaMinutes": 480 + }, + { + "backupRunType": "kFull", + "slaMinutes": 480 + } + ], + "isPaused": True, + "environment": "kAzure", + "azureParams": { + "protectionType": "kNative", + "nativeProtectionTypeParams":{ + "objects": [], + "vmTagIds": [ + [ + tagId + ] + ], + "indexingPolicy":{ + "enableIndexing": True, + "includePaths": [ + "/" + ], + "excludePaths": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/splunk", + ] + }, + "sourceId": parentId + }, + }, + "abortInBlackoutPeriod": False + } + + encoded_payload = json.dumps(payload) + print(base_url + apiCall) + response = requests.request("POST", base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CreateSQLProtectionJob(self, srcId, pgName): + apiCall = "/public/protectionJobs/" + payload = { + "name": pgName, + + # NDIT - Bronze Policy + "policyId": "4847477517838800:1610060943809:6402", + + # Default Storage Domain + "viewBoxId": 198, + + # SQL Server kRootContainer + "parentSourceId": 8702, + + "sourceIds": [ + srcId + ], + + "startTime": { + "hour": 22, + "minute": 00 + }, + + "timezone": "America/Chicago", + + "fullProtectionSlaTimeMins": 480, + "incrementalProtectionSlaTimeMins": 480, + "priority": "kLow", + "LeverageSanTransport": False, + + # Default Indexing Policy + "indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }, + + "environment": "kSQL", + "environmentParameters": { + "sqlParameters": { + "userDatabasePreference": "kBackupAllDatabases", + "backupSystemDatabases": bool('true'), + "aagPreferenceFromSqlServer": bool('true'), + "backupType": "kSqlVSSVolume", + "backupVolumesOnly": bool('true') + } + + }, + + "abortInBlackoutPeriod": False, + "qosType": "kBackupHDD", + "description": "", + "isPaused": False + } + + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + + def CreatePhysicalProtectionJob(self, srcId, pgName): + apiCall = "/public/protectionJobs/" + payload = { + "name": pgName, + "environment": "kPhysical", + + # NDIT - Bronze Policy + "policyId": "4847477517838800:1610060943809:6402", + + # Default Storage Domain + "viewBoxId": 198, + + # Physical Servers + "parentSourceId": 3149, + + "sourceIds": [ + srcId + ], + + "startTime": { + "hour": 18, + "minute": 00 + }, + + "timezone": "America/Chicago", + + "fullProtectionSlaTimeMins": 480, + "incrementalProtectionSlaTimeMins": 480, + "priority": "kLow", + "LeverageSanTransport": False, + + # Default Indexing Policy + "indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }, + + "abortInBlackoutPeriod": False, + "performSourceSideDedup": True, + "qosType": "kBackupHDD", + "description": "", + "isPaused": False + } + encoded_payload = json.dumps(payload) + response = requests.request("POST", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) + +################ Security Methods ####################### + + def UpdatePermissions(self, sourceIds, cohesitySid): + apiCall = "/public/principals/protectionSources" + payload = { + "sourcesForPrincipals": [ + { + "protectionSourceIds": sourceIds, + "sid": cohesitySid + } + ] + } + encoded_payload = json.dumps(payload) + response = requests.request("PUT", self.base_url + apiCall, headers=self.headers, data=encoded_payload) + return (response) diff --git a/_NDGOV_CS/ITD.Cohesity/classes/itdSnow.py b/_NDGOV_CS/ITD.Cohesity/classes/itdSnow.py new file mode 100644 index 0000000..eeefa28 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/classes/itdSnow.py @@ -0,0 +1,502 @@ +import requests +import json +import os +import pytz +from datetime import datetime +from datetime import timedelta +from datetime import time + +# API Documentation +# https://docs.servicenow.com/bundle/sandiego-application-development/page/build/applications/concept/api-rest.html + +class SnowAPI: + def __init__(self, snInstance): + if not ((os.environ.get('SN_USER')) and (os.environ.get('SN_PASS'))): + print("\n*** Environment variables are not set for ServiceNow Authentication ***") + exit() + + self.snInstance = snInstance + self.headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + + self.user = os.environ['SN_USER'] + self.pwd = os.environ['SN_PASS'] + + def getGroupID(self, grpName): + grpName = grpName.replace(" ","%20") + url = 'https://{}/api/now/table/sys_user_group?sysparm_query=name={}'.format(self.snInstance, grpName) + apiResponse = requests.get(url, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0]['sys_id'] + + def getUserID(self, userName): + userName = userName.replace(" ","%20") + apiCall = 'https://{}/api/now/table/sys_user?sysparm_query=user_name={}'.format(self.snInstance, userName) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0]['sys_id'] + + def getCMDBItemByIP(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=ip_address={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + + return apiData['result'] + + def getCMDBItemByHostName(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=host_name={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + + return apiData['result'] + + def getCMDBItemByFQDN(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=fqdn={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + if len(apiData['result']) > 0: + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + print("Result 2: {0}".format(apiData)) + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + return apiData['result'] + + def getCMDBAppById(self, sysId): + apiCall = "https://{0}/api/now/table/cmdb_ci_service_auto?sys_id={1}".format(self.snInstance, sysId) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0] + + def getStandardChangeTemplateID(self, templateName): + # Could be improved, might throw unexpected results if the group isn't found + # Needs error handling + + allData = [] + + apiCall = "https://{0}/api/sn_chg_rest/change/standard/template?sysparm_query=active=true".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + + for i in data['result']: + allData.append(i) + + for record in allData: + if 'sys_name' in record: + if record['sys_name']['display_value'] == templateName: + sysID = record['sys_id']['value'] + break + + return sysID + + def getRequestItemFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_req_item?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['number'] + + return item + + def getTaskNumFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['number'] + + return item + + def getTaskSysIdFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['sys_id'] + + return item + + def getServiceCatalogs(self): + apiCall = "https://{0}/api/sn_sc/servicecatalog/catalogs".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogCategories(self, sys_id): + apiCall = "https://{0}/api/sn_sc/servicecatalog/catalogs/{1}/categories".format(self.snInstance,sys_id) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogItems(self): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items?sysparm_limit=10000&sysparm_offset=0".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogItemByName(self, itemName): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items?sysparm_limit=10000&sysparm_offset=0".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + for item in items['result']: + if item['name'] == itemName: + return item + + def getSpecificCatalogItem(self, sysId): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items/{1}".format(self.snInstance,sysId) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getDataFromTaskByReqNum(self, sctask, reqNum): + # This is only written to handle one task per REQ number!!! + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_fields=state%2Cnumber%2Csys_id%2Cdescription%2Cshort_description%2Cvariables.application_name%2Cvariables.additional_comments%2Cclose_notes%2Cclosed_by&sysparm_limit=1&sysparm_display_value=true".format(self.snInstance, reqNum) + + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + + if data['result'][0]['number'] == sctask: + items = data['result'][0] + else: + items = "" + + return items + + def updateTaskDescriptions(self, sysId, short_desc, desc): + apiCall = "https://{0}/api/now/table/sc_task/{1}".format(self.snInstance,sysId) + + payload = { + 'short_description': short_desc, + 'description': desc + } + encoded_payload = json.dumps(payload) + apiResponse = requests.put(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to update task:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assignTaskToUser(self, sysId, userName): + userID = self.getUserID(userName) + apiCall = "https://{0}/api/now/table/sc_task/{1}".format(self.snInstance,sysId) + payload = { + "assigned_to": userID + } + + encoded_payload = json.dumps(payload) + apiResponse = requests.put(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to update task:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def postAppServerRequest(self,itemID,requestFor,requestBy,approver,requestType,comments,appName,env): + requestForID = self.getUserID(requestFor) + requestByID = self.getUserID(requestBy) + approvalID = self.getUserID(approver) + + # Statically set these so we always force approvals to go to Computer Systems + departmentID = "f3c65cef1bfed050bba0113fad4bcb1d" + departmentCode = "112" + divisionID = "f40758231b321450bba0113fad4bcb2d" + divisionCode = "32" + + payload = { + "get_portal_messages" : "true", + "sysparm_quantity" : "1", + "sysparm_no_validation" : "true", + "variables" : { + "v_approval_department" : departmentID, + "v_approval_department_code" : departmentCode, + "v_approval_division" : divisionID, + "v_approval_division_code" : divisionCode, + "v_manager" : approvalID, + "v_requested_by" : requestByID, + "v_requested_for" : requestForID, + "request_type" : requestType, + "additional_comments" : comments, + "application_name" : appName, + "environment" : env, + "require_hosting_quote" : "No", + "add_change_disaster_recovery" : "No" + } + } + + apiCall = ('https://{0}/api/sn_sc/v1/servicecatalog/items/{1}/order_now').format(self.snInstance,itemID) + + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + return apiResponse + + def postGenericSerivceRequest(self,itemID,requestFor,requestBy,approver,requestType,comments): + requestForID = self.getUserID(requestFor) + requestByID = self.getUserID(requestBy) + approvalID = self.getUserID(approver) + departmentID = "f3c65cef1bfed050bba0113fad4bcb1d" + divisionID = "f40758231b321450bba0113fad4bcb2d" + + payload = { + "get_portal_messages" : "true", + "sysparm_quantity" : "1", + "sysparm_no_validation" : "true", + "variables" : { + "v_approval_department" : departmentID, + "v_approval_division" : divisionID, + "v_manager" : approvalID, + "v_requested_by" : requestByID, + "v_requested_for" : requestForID, + "v_type" : requestType, + "additional_comments" : comments + } + } + + apiCall = ('https://{0}/api/sn_sc/v1/servicecatalog/items/{1}/order_now').format(self.snInstance,itemID) + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + return apiResponse + + def getGenericData(self, url): + apiCall = "https://{0}/".format(self.snInstance,url) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def submitTicket(self, user, subject, content): + apiCall = ('https://{}/api/now/table/incident').format(self.snInstance) + userID=self.getUserID(user) + + payload = { + 'caller_id': userID, + 'short_description': subject, + 'description': content + } + + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assignTicketToGroup(self, sysId, grpName): + grpId = self.getGroupID(grpName) + url = 'https://{}/api/now/table/incident/{}'.format(self.snInstance,sysId) + + #Statically set the group to storage, this value was derived by decoding the web URL on storage tickets + payload = { + 'assignment_group': grpId + } + encoded_payload = json.dumps(payload) + apiResponse = requests.put(url, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assessNormalChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/normal/{1}".format(self.snInstance,sysID) + payload = { + "state": "assess" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def addStandardChangeNotes(self, sysID, txtWorkNotes): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,sysID) + payload = { + "work_notes": txtWorkNotes + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def scheduleStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,sysID) + payload = { + "state": "Scheduled" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def implementStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Implement" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def reviewStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Review" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def closeStandardChange(self, sysID, code, notes): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Closed", + "close_code": code, + "close_notes": notes + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def CreateNormalChange(self, grpName, assignee, coordinator, approver, category, subCategory, shortDesc, desc, justDesc, implmntPlan, riskImpact, backoutPlan, testPlan, sTime, eTime): + + # Creates a normal change request that will require approval. + + grpID = self.getGroupID(grpName) + userID = self.getUserID(assignee) + chngCoordID = self.getUserID(coordinator) + chngMngrID = self.getUserID(approver) + + apiCall = "https://{0}/api/sn_chg_rest/change/normal".format(self.snInstance) + + 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, + } + encoded_payload=json.dumps(payload) + changeResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + changeData = changeResponse.json() + + return changeData + + def CreateStandardChange(self, templateName, grpName, assignee, coordinator, approver, category, subcategory, txtShortDesc, txtJustification): + templateID = self.getStandardChangeTemplateID(templateName) + grpID = self.getGroupID(grpName) + userID = self.getUserID(assignee) + chngCoordID = self.getUserID(coordinator) + chngMngrID = self.getUserID(approver) + + sTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + eTime = (datetime.now()+timedelta(minutes=+1)).strftime("%Y-%m-%d %H:%M:%S") + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,templateID) + + payload={ + "category": category, + "u_subcategory": subcategory, + "u_change_manager": chngMngrID, + "assigned_to": userID, + "u_change_coordinator": chngCoordID, + "assignment_group": grpID, + "short_description": txtShortDesc, + "justification": txtJustification, + "start_date": sTime, + "end_date": eTime + } + encoded_payload=json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + +######################################### END CLASS ################################ diff --git a/_NDGOV_CS/ITD.Cohesity/classes/serviceNowAPI.py b/_NDGOV_CS/ITD.Cohesity/classes/serviceNowAPI.py new file mode 100644 index 0000000..eeefa28 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/classes/serviceNowAPI.py @@ -0,0 +1,502 @@ +import requests +import json +import os +import pytz +from datetime import datetime +from datetime import timedelta +from datetime import time + +# API Documentation +# https://docs.servicenow.com/bundle/sandiego-application-development/page/build/applications/concept/api-rest.html + +class SnowAPI: + def __init__(self, snInstance): + if not ((os.environ.get('SN_USER')) and (os.environ.get('SN_PASS'))): + print("\n*** Environment variables are not set for ServiceNow Authentication ***") + exit() + + self.snInstance = snInstance + self.headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + + self.user = os.environ['SN_USER'] + self.pwd = os.environ['SN_PASS'] + + def getGroupID(self, grpName): + grpName = grpName.replace(" ","%20") + url = 'https://{}/api/now/table/sys_user_group?sysparm_query=name={}'.format(self.snInstance, grpName) + apiResponse = requests.get(url, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0]['sys_id'] + + def getUserID(self, userName): + userName = userName.replace(" ","%20") + apiCall = 'https://{}/api/now/table/sys_user?sysparm_query=user_name={}'.format(self.snInstance, userName) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0]['sys_id'] + + def getCMDBItemByIP(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=ip_address={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + + return apiData['result'] + + def getCMDBItemByHostName(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=host_name={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + + return apiData['result'] + + def getCMDBItemByFQDN(self, pattern): + apiCall = "https://{0}/api/now/table/cmdb_ci_server?sysparm_query=fqdn={1}&sysparm_limit=10".format(self.snInstance, pattern) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + if len(apiData['result']) > 0: + try: + appNameRec = self.getCMDBAppById(apiData['result'][0]['u_nd_application_svc']['value']) + appName = appNameRec['name'] + apiData['result'][0].update({ + "u_nd_application_svc": { + "link": apiData['result'][0]['u_nd_application_svc']['link'], + "value": apiData['result'][0]['u_nd_application_svc']['value'], + "name": appName + } + }) + except: + print("Result 2: {0}".format(apiData)) + apiData['result'][0].update({ + "u_nd_application_svc": { + "name": "UNDEFINED" + }, + "environment": "UNDEFINED" + }) + return apiData['result'] + + def getCMDBAppById(self, sysId): + apiCall = "https://{0}/api/now/table/cmdb_ci_service_auto?sys_id={1}".format(self.snInstance, sysId) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + apiData = apiResponse.json() + + return apiData['result'][0] + + def getStandardChangeTemplateID(self, templateName): + # Could be improved, might throw unexpected results if the group isn't found + # Needs error handling + + allData = [] + + apiCall = "https://{0}/api/sn_chg_rest/change/standard/template?sysparm_query=active=true".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + + for i in data['result']: + allData.append(i) + + for record in allData: + if 'sys_name' in record: + if record['sys_name']['display_value'] == templateName: + sysID = record['sys_id']['value'] + break + + return sysID + + def getRequestItemFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_req_item?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['number'] + + return item + + def getTaskNumFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['number'] + + return item + + def getTaskSysIdFromReqNum(self, reqNum): + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_limit=1".format(self.snInstance, reqNum) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + item = data['result'][0]['sys_id'] + + return item + + def getServiceCatalogs(self): + apiCall = "https://{0}/api/sn_sc/servicecatalog/catalogs".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogCategories(self, sys_id): + apiCall = "https://{0}/api/sn_sc/servicecatalog/catalogs/{1}/categories".format(self.snInstance,sys_id) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogItems(self): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items?sysparm_limit=10000&sysparm_offset=0".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getServiceCatalogItemByName(self, itemName): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items?sysparm_limit=10000&sysparm_offset=0".format(self.snInstance) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + for item in items['result']: + if item['name'] == itemName: + return item + + def getSpecificCatalogItem(self, sysId): + apiCall = "https://{0}/api/sn_sc/servicecatalog/items/{1}".format(self.snInstance,sysId) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def getDataFromTaskByReqNum(self, sctask, reqNum): + # This is only written to handle one task per REQ number!!! + apiCall = "https://{0}/api/now/table/sc_task?sysparm_query=request.number={1}&sysparm_fields=state%2Cnumber%2Csys_id%2Cdescription%2Cshort_description%2Cvariables.application_name%2Cvariables.additional_comments%2Cclose_notes%2Cclosed_by&sysparm_limit=1&sysparm_display_value=true".format(self.snInstance, reqNum) + + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + data = apiResponse.json() + + if data['result'][0]['number'] == sctask: + items = data['result'][0] + else: + items = "" + + return items + + def updateTaskDescriptions(self, sysId, short_desc, desc): + apiCall = "https://{0}/api/now/table/sc_task/{1}".format(self.snInstance,sysId) + + payload = { + 'short_description': short_desc, + 'description': desc + } + encoded_payload = json.dumps(payload) + apiResponse = requests.put(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to update task:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assignTaskToUser(self, sysId, userName): + userID = self.getUserID(userName) + apiCall = "https://{0}/api/now/table/sc_task/{1}".format(self.snInstance,sysId) + payload = { + "assigned_to": userID + } + + encoded_payload = json.dumps(payload) + apiResponse = requests.put(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to update task:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def postAppServerRequest(self,itemID,requestFor,requestBy,approver,requestType,comments,appName,env): + requestForID = self.getUserID(requestFor) + requestByID = self.getUserID(requestBy) + approvalID = self.getUserID(approver) + + # Statically set these so we always force approvals to go to Computer Systems + departmentID = "f3c65cef1bfed050bba0113fad4bcb1d" + departmentCode = "112" + divisionID = "f40758231b321450bba0113fad4bcb2d" + divisionCode = "32" + + payload = { + "get_portal_messages" : "true", + "sysparm_quantity" : "1", + "sysparm_no_validation" : "true", + "variables" : { + "v_approval_department" : departmentID, + "v_approval_department_code" : departmentCode, + "v_approval_division" : divisionID, + "v_approval_division_code" : divisionCode, + "v_manager" : approvalID, + "v_requested_by" : requestByID, + "v_requested_for" : requestForID, + "request_type" : requestType, + "additional_comments" : comments, + "application_name" : appName, + "environment" : env, + "require_hosting_quote" : "No", + "add_change_disaster_recovery" : "No" + } + } + + apiCall = ('https://{0}/api/sn_sc/v1/servicecatalog/items/{1}/order_now').format(self.snInstance,itemID) + + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + return apiResponse + + def postGenericSerivceRequest(self,itemID,requestFor,requestBy,approver,requestType,comments): + requestForID = self.getUserID(requestFor) + requestByID = self.getUserID(requestBy) + approvalID = self.getUserID(approver) + departmentID = "f3c65cef1bfed050bba0113fad4bcb1d" + divisionID = "f40758231b321450bba0113fad4bcb2d" + + payload = { + "get_portal_messages" : "true", + "sysparm_quantity" : "1", + "sysparm_no_validation" : "true", + "variables" : { + "v_approval_department" : departmentID, + "v_approval_division" : divisionID, + "v_manager" : approvalID, + "v_requested_by" : requestByID, + "v_requested_for" : requestForID, + "v_type" : requestType, + "additional_comments" : comments + } + } + + apiCall = ('https://{0}/api/sn_sc/v1/servicecatalog/items/{1}/order_now').format(self.snInstance,itemID) + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + return apiResponse + + def getGenericData(self, url): + apiCall = "https://{0}/".format(self.snInstance,url) + apiResponse = requests.get(apiCall, auth=(self.user, self.pwd), headers=self.headers) + items = apiResponse.json() + + return items + + def submitTicket(self, user, subject, content): + apiCall = ('https://{}/api/now/table/incident').format(self.snInstance) + userID=self.getUserID(user) + + payload = { + 'caller_id': userID, + 'short_description': subject, + 'description': content + } + + encoded_payload = json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assignTicketToGroup(self, sysId, grpName): + grpId = self.getGroupID(grpName) + url = 'https://{}/api/now/table/incident/{}'.format(self.snInstance,sysId) + + #Statically set the group to storage, this value was derived by decoding the web URL on storage tickets + payload = { + 'assignment_group': grpId + } + encoded_payload = json.dumps(payload) + apiResponse = requests.put(url, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + + if apiResponse.status_code != 201 and apiResponse.status_code != 200: + print('Failed to create ticket:') + print('\tStatus:', apiResponse.status_code) + print('\tError Response:',apiResponse.json()) + exit(1) + else: + return apiResponse.json() + + def assessNormalChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/normal/{1}".format(self.snInstance,sysID) + payload = { + "state": "assess" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def addStandardChangeNotes(self, sysID, txtWorkNotes): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,sysID) + payload = { + "work_notes": txtWorkNotes + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def scheduleStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,sysID) + payload = { + "state": "Scheduled" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def implementStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Implement" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def reviewStandardChange(self, sysID): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Review" + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def closeStandardChange(self, sysID, code, notes): + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance, sysID) + payload = { + "state": "Closed", + "close_code": code, + "close_notes": notes + } + encoded_payload=json.dumps(payload) + apiResponse = requests.patch(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + + def CreateNormalChange(self, grpName, assignee, coordinator, approver, category, subCategory, shortDesc, desc, justDesc, implmntPlan, riskImpact, backoutPlan, testPlan, sTime, eTime): + + # Creates a normal change request that will require approval. + + grpID = self.getGroupID(grpName) + userID = self.getUserID(assignee) + chngCoordID = self.getUserID(coordinator) + chngMngrID = self.getUserID(approver) + + apiCall = "https://{0}/api/sn_chg_rest/change/normal".format(self.snInstance) + + 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, + } + encoded_payload=json.dumps(payload) + changeResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + changeData = changeResponse.json() + + return changeData + + def CreateStandardChange(self, templateName, grpName, assignee, coordinator, approver, category, subcategory, txtShortDesc, txtJustification): + templateID = self.getStandardChangeTemplateID(templateName) + grpID = self.getGroupID(grpName) + userID = self.getUserID(assignee) + chngCoordID = self.getUserID(coordinator) + chngMngrID = self.getUserID(approver) + + sTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + eTime = (datetime.now()+timedelta(minutes=+1)).strftime("%Y-%m-%d %H:%M:%S") + apiCall = "https://{0}/api/sn_chg_rest/change/standard/{1}".format(self.snInstance,templateID) + + payload={ + "category": category, + "u_subcategory": subcategory, + "u_change_manager": chngMngrID, + "assigned_to": userID, + "u_change_coordinator": chngCoordID, + "assignment_group": grpID, + "short_description": txtShortDesc, + "justification": txtJustification, + "start_date": sTime, + "end_date": eTime + } + encoded_payload=json.dumps(payload) + apiResponse = requests.post(apiCall, auth=(self.user, self.pwd), headers=self.headers, data=encoded_payload) + return apiResponse.json() + +######################################### END CLASS ################################ diff --git a/_NDGOV_CS/ITD.Cohesity/classes/sharePointAPI.py b/_NDGOV_CS/ITD.Cohesity/classes/sharePointAPI.py new file mode 100644 index 0000000..ea67ea7 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/classes/sharePointAPI.py @@ -0,0 +1,175 @@ +import os +import argparse +import json +import urllib3 +import requests +from requests_ntlm import HttpNtlmAuth +# Use pip install requests_ntlm to install the necessary modules + +class API(object): + def __init__(self): + if not ((os.environ.get('ITD_SHAREPOINT_PASS')) and (os.environ.get('ITD_SHAREPOINT_USER'))): + print("\n*** ERROR: Environment Variables are not set for SharePoint ***") + print("Set OS environment variables ITD_SHAREPOINT_PASS and ITD_SHAREPOINT_USER") + exit(1) + else: + # Username is in the format of 'NDGOV\\' + sp_user = os.environ['ITD_SHAREPOINT_USER'] + sp_pass = os.environ['ITD_SHAREPOINT_PASS'] + + self.server_url = "https://share.nd.gov/" + self.site_url = self.server_url + "itd/Computer-Systems/Distributed-Systems/VMWare/_api/web/" + self.context_url = self.server_url + "itd/Computer-Systems/Distributed-Systems/VMWare/_api/contextinfo/" + self.env = "All" + + self.headers = { + "Accept":"application/json; odata=verbose", + "Content-Type":"application/json; odata=verbose", + "odata":"verbose", + "X-RequestForceAuthentication":"true" + } + + self.auth = HttpNtlmAuth(sp_user, sp_pass) + + def get_AllNodes(self): + + list_name = 'VM Guests' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + list_itemcount = r.json()['d']['ItemCount'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + concat_items = [] + # Parse the list + requests.packages.urllib3.disable_warnings() + cur_page = requests.get(api_items_url, auth=self.auth, headers=self.headers, verify=False) + concat_items += cur_page.json()['d']['results'] + + # Sharepoint uses pagination with '__next' in the JSON results to indicate additional pages of information + # are present. Loop through the pages and concatenate the information into one dataset + while '__next' in cur_page.json()['d']: + requests.packages.urllib3.disable_warnings() + cur_page = requests.get(cur_page.json()['d']['__next'], auth=self.auth, headers=self.headers, verify=False) + concat_items += cur_page.json()['d']['results'] + + return concat_items + + def get_ActiveNodes(self, e): + + self.env = e + list_name = 'VM Guests' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + list_itemcount = r.json()['d']['ItemCount'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + if self.env == 'All': + active_items_url = api_items_url + "?$filter=(Status eq 'Current') or (Status eq 'Change')" + else: + active_items_url = api_items_url + "?$filter=(Environment eq '%s') and ((Status eq 'Current') or (Status eq 'Change'))" % self.env + concat_items = [] + + # Parse the list + requests.packages.urllib3.disable_warnings() + cur_page = requests.get(active_items_url, auth=self.auth, headers=self.headers, verify=False) + concat_items += cur_page.json()['d']['results'] + + # Sharepoint uses pagination with '__next' in the JSON results to indicate additional pages of information + # are present. Loop through the pages and concatenate the information into one dataset + while '__next' in cur_page.json()['d']: + requests.packages.urllib3.disable_warnings() + cur_page = requests.get(cur_page.json()['d']['__next'], auth=self.auth, headers=self.headers, verify=False) + concat_items += cur_page.json()['d']['results'] + + return concat_items + + def find_VM(self, hostname): + + domains = [".nd.gov", ".ndtestdev.nd.dev", ".ndcloud.gov", ".testnd.gov", ".itd.nd.gov", ".ns.nd.gov", ".cloudapp.azure.com", ".uat.mmis.nd.gov", ".test.ndcloud.gov", ".k12tst.nd.us", ".legend.nd.gov", ".tst.mmis.dev", ".trn.mmis.nd.gov", ".sit.mmis.nd.gov", ".nd.gov-mag", ".uat.mmis.dev", ".mo.legend.nd.gov", ".video.nd.gov", ".mmis.nd.gov", ".sit.legend.nd.gov", ".trn.mmis.dev", ".prm.mmis.nd.gov", ".state.nd.us", ".k12.nd.us", ".stg.k12.nd.us", ".sit.mmis.dev", "ndnic.com"] + + for domain in domains: + try: + data = self.get_Node(hostname + domain) + if 'Title' in data[0]: + hostname = data[0]['Title'] + break + except: + continue + + return(hostname) + + def get_Node(self, server): + + myNode = server + list_name = 'VM Guests' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + singleServer_url = api_items_url + "?$filter=Title eq '%s'" % myNode + cur_page = requests.get(singleServer_url, auth=self.auth, headers=self.headers, verify=False) + + return cur_page.json()['d']['results'] + + def get_Agency(self, aID): + + agencyID = aID + list_name = 'Agency' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + singleServer_url = api_items_url + "?$filter=ID eq '%s'" % agencyID + cur_page = requests.get(singleServer_url, auth=self.auth, headers=self.headers, verify=False) + + return cur_page.json()['d']['results'][0]['Title'] + + def get_AppName(self, appID): + + applicationID = appID + list_name = 'VM App Name' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + singleServer_url = api_items_url + "?$filter=ID eq '%s'" % applicationID + cur_page = requests.get(singleServer_url, auth=self.auth, headers=self.headers, verify=False) + + return cur_page.json()['d']['results'][0]['Title'] + + def get_AppNodes(self, appID): + + applicationID = appID + list_name = 'VM Guests' + + # Get list information + requests.packages.urllib3.disable_warnings() + r = requests.get(self.site_url + "lists/GetByTitle('%s')" % list_name, auth=self.auth, headers=self.headers, verify=False) + list_guid = r.json()['d']['Id'] + + # Query list items + api_items_url = self.site_url + "Lists(guid'%s')/Items" % list_guid + singleServer_url = api_items_url + "?$filter=AppName eq '%s'" % appID + cur_page = requests.get(singleServer_url, auth=self.auth, headers=self.headers, verify=False) + + return cur_page.json()['d']['results'] diff --git a/_NDGOV_CS/ITD.Cohesity/dailyBackupReview.py b/_NDGOV_CS/ITD.Cohesity/dailyBackupReview.py new file mode 100644 index 0000000..4cc16aa --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/dailyBackupReview.py @@ -0,0 +1,770 @@ +#!/usr/bin/python +#-------------------------------------------------------------------------------------------------# +# Author: Cliff Cogdill +# Description: This script accomplishes a few things: +# - Reviews all assets in the CMDB to determine if they have been setup in backups. +# - If not, identify them and send create a ticket for investigation. +# - Reviews paused protection jobs to determine if the job is still empty. +# - If not empty, resume the job. +# - Send summary report of unprotected servers and VM jobs to the storage team. +# ------------------------------------------------------------------------------------------------# + +import sys,argparse,json,time,yaml,re,smtplib +from email.message import EmailMessage +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import sharePointAPI as sharePoint +import automationsAPI as dashboard +import serviceNowAPI as snow +#import nditServiceNow as snow +import logging +#import pymsteams + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--debug', '-d', action='store_true') + parser.add_argument('--excludeTickets', '-x', action='store_true') + parser.add_argument('--refresh', '-r', action='store_true') + parser.add_argument('--type', '-t', type=str, action='store') + parser.add_argument('--vCenter', '-v', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def SendEmail(body, cluster): + + if debug: + recipients = ['itbackups@nd.gov'] + else: + recipients = ['zmeier@nd.gov', 'cecogdill@nd.gov','khellman@nd.gov','mlaverdure@nd.gov','ndheck@nd.gov'] + + email = EmailMessage() + email['Subject'] = "Backup Review for {0}".format(cluster) + email['From'] = "No-Reply@nd.gov" + email['To'] = ", ".join(recipients) + email.set_content(body) + + with smtplib.SMTP('apprelay.nd.gov') as smtp: + smtp.send_message(email) + + if args.debug: + print("Sent email") + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 protectedItems.py -c cluster1.domain.tld [ -v vCenter.domain.tld ] [ -j protectionJobName ]") + print("\t -d debug: execute in debug mode to expand summary and do not open tickets") + print("\t -x excludeTickets: run against prod serivce now but do not open tickets or changes") + print("\t -r refresh: force source refresh in debug mode") + print("\t -c FQDN of Cohesity cluster address") + print("\t -t type of protection source") + print("\t -h Prints this help message") + +#itdTeamsMessage = pymsteams.connectorcard("https://ndgov.webhook.office.com/webhookb2/aad89030-8f69-4a4d-a853-c882cbb01a10@2dea0464-da51-4a88-bae2-b3db94bc0c54/IncomingWebhook/d3c07921419c4920810d0c32558c05e3/edcc1502-1ff0-4c3e-9fe2-1ce3f9f7981a") + +args = GetArgs() + +if args.help: + PrintHelp() + exit() + +logging.basicConfig(filename="log/" + args.cluster + '.log', filemode='w', format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %I:%M:%S %p', level=logging.DEBUG) + +# Define empty lists that will hold JSON dictionaries +vmObjects = [] +protectedObjects = [] +vCenters = [] + +protectedVM = [] +unprotectedVM = [] +undocumentedVM = [] +vmExemptions = [] + +populatedJobs = [] +populatedPausedJobs = [] +jobExemptions = [] +emptyJobs = [] + +tickets = [] + + +# Default to the main cluster on premise if the cluster argument was not specified +if not args.cluster: + args.cluster = "itdmdndpc01.nd.gov" + args.type = "kVMware" + +if not args.type: + args.type = "kVMware" + +if args.cluster == "itdazdpc01.nd.gov": + args.type = "kAzure" + +if args.cluster == "itdazdpc02.nd.gov": + args.type = "kAzure" + +logging.info("Creating cluster object for {0} with type {1}".format(args.cluster, args.type)) + +# Setup the token for cluster API usage +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Lookup the AppNames and vCenter for unprotected VMs +logging.info("Creating cmdb object for SharePoint list") +#cmdb = sharePoint.API() +cmdb = snow.SnowAPI("northdakota.service-now.com") + +# When true, tickets will only be created in ServiceNow dev and JSON output may be expanded to stdout +if args.debug: + debug = True +else: + debug = False + +if args.excludeTickets: + excludeTickets = True +else: + excludeTickets = False + +# Create the connection to ServiceNow +logging.info("Creating ticketSystem object for ServiceNow") + +if debug: + ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") +else: + ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +if args.type == "kPhysical": + physicalJobs = cluster.GetPhysicalJobs() + sys.exit("Warning: Type not implmented for this script.") + +elif args.type == "kSQL": + sys.exit("Warning: Type not implmented for this script.") + +elif args.type == "kAzure": + + # Get all registered subscription sources so we can use the source ids for other REST calls + logging.info("Collecting all registered Azure sources") + nodes = cluster.GetAZsources() + + # Iterate through all the Azure subscriptions to create one large dataset for all VMs + logging.info("Creating dataset for all VMs in our Azure subscriptions") + logging.info("Creating dataset for all protected VMs in our Azure subscriptions") + for node in nodes: + hypervisorId = node['protectionSource']['id'] + + #Refresh the sources so we ensure we are getting valid information + if debug: + print("Debug enabled, not refreshing source use -r option to override") + else: + cluster.RefreshSource(node['protectionSource']['id']) + + if args.refresh: + cluster.RefreshSource(node['protectionSource']['id']) + + myObjects = cluster.GetAZObjects(hypervisorId) + myProtectedObjects = cluster.GetProtectedAZobjects(hypervisorId) + + # Combine all VM objects into one dictionary + for val in myObjects: + vmObjects.append(val) + + # Combine all protected objects into one dictionary + for val in myProtectedObjects: + protectedObjects.append(val) + + # Get all the native snapshot protection jobs that exist in the cluster + logging.info("Gathering all current protection jobs from {0}".format(args.cluster)) + sourceJobs = cluster.GetAZNativeJobs() + +elif args.type == "kVMware": + # Get all registered vCenter sources so we can use the source ids for other REST calls + logging.info("Collecting all registered vmWare sources") + nodes = cluster.GetVMsources() + + # Iterate through all the vCenter servers to create one large dataset for all VMs + logging.info("Creating dataset for all VMs in our Azure subscriptions") + logging.info("Creating dataset for all protected VMs in our Azure subscriptions") + for node in nodes: + hypervisorId = node['protectionSource']['id'] + + #Refresh the sources so we ensure we are getting valid information + cluster.RefreshSource(node['protectionSource']['id']) + + myObjects = cluster.GetVMObjects(hypervisorId) + myProtectedObjects = cluster.GetProtectedVMobjects(hypervisorId) + + # Combine all VM objects into one dictionary + for val in myObjects: + vmObjects.append(val) + + # Combine all protected objects into one dictionary + for val in myProtectedObjects: + protectedObjects.append(val) + + # At this point we have two sets of data + # 1. All vms objects whether they are protected or not ( vmObjects ) + # 2. All protected vm objects ( protectedObjects ) + + # Get all the protection jobs that exist for vmware in the cluster + logging.info("Gathering all current protection jobs from {0}".format(args.cluster)) + sourceJobs = cluster.GetVMjobs() + +if args.type == "kVMware" or args.type == "kAzure": + +############################## BEGIN: IDENTIFY EMPTY & POPULATE PAUSED JOBS ####################################### + # Loop through the sourceJobs to see if they show up in at least once in the list of protected objects. + # if they don't show up, we can assume the job is created but empty, which is usually the case for + # placeholder VMs + + # In certain circumstances, jobs can be defined but exempt from normal processing. These jobs are normally used from time to time for POC work and do not necessarily need to be protected, here we will load them into the exempt jobs array from the exceptions.yml file. + logging.info("Opening exemptions file: vars/exemptions.yml") + with open("./vars/exemptions.yml", "r") as exemptionJobData: + try: + exemptionJobData = yaml.load(exemptionJobData, Loader=yaml.FullLoader) + except: + print("Unable to load exemptions file.") + + exemptJobs = [] + + logging.info("Parsing exemptions YAML") + for i in exemptionJobData: + for e in exemptionJobData[i]['jobs']: + #exemptJobs.append(e.lower()) + exemptJobs.append([exemptionJobData[i]['id'],e.lower()]) + + # Loop through all the jobs for + logging.info("Iterating through all protection jobs") + print("Starting interation of all protection jobs") + for sourceJob in sourceJobs: + + #Set default control variables for each job + isJobExempt = False + isJobEmpty = True + + # The REST GetVMjobs function returns unfiltered jobs, so lets get rid of the deleted ones + if 'isDeleted' in sourceJob: + if sourceJob['isDeleted'] == True: + logging.info("--Job {0} is marked for deletion, skipping review".format(sourceJob['name'])) + continue + + # Look through the exemptJobs listing + for entry in exemptJobs: + parent = entry[0] + pattern = entry[1] + + if parent == sourceJob['parentSourceId']: + if re.search(pattern, sourceJob['name'].lower()): + isJobExempt = True + break + + if isJobExempt == True: + jobExemptions.append(sourceJob['name']) + if debug == True: + logging.info("--Job {0} has been exempt from backups, skipping review".format(sourceJob['name'])) + print("Job {0} is exempt from tickets".format(sourceJob['name'])) + continue + + # The protection jobs only show tags, they do not show VM ojbects; therefore, to determine if the job is still valid, we have to iterate through all protected objects to see if the job name shows up or not. If it does not show up, then it is assumed to be empty and paused to prevent backup errors. Also, there is usually only one job listed per protected VM; however, there could be cases where a VM is in two or more jobs so we need to check each job listed. + # Sample dataset can be seen by using the following url: + # https://itdmdndpc01.nd.gov/irisservices/api/v1/public/protectionSources/protectedObjects?environment=kVMware&id=3156 + logging.info("--Iterating through all protected objects to verify if job {0} is empty".format(sourceJob['name'])) + for item in protectedObjects: + for pJob in item['protectionJobs']: + if pJob['name'] == sourceJob['name']: + isJobEmpty = False + continue + + # Seperate empty from non-empty jobs + if isJobEmpty: + logging.info("--{0} is empty, pausing future runs".format(sourceJob['name'])) + emptyJobs.append(sourceJob) + # Pause the job so we don't generate erroneous errors. + cluster.PauseJob(sourceJob['id']) + + else: + # The job is not empty, lets check to see if it is paused so we can create an alert. + + # First we have to check if the isPaused key exists, if it has never been set, it will not. + if 'isPaused' in sourceJob: + # Now we check to see if isPaused is set to True + if sourceJob['isPaused']: + logging.info("----{0} is paused but contains VM objects, adding to populatedPausedJobs dataset".format(sourceJob['name'])) + populatedPausedJobs.append(sourceJob) + # isPaused might be defined but it is set to False + else: + populatedJobs.append(sourceJob) + + # If the job has never been paused, isPaused may not be defined + else: + populatedJobs.append(sourceJob) + +############################## END: IDENTIFY EMPTY & POPULATE JOBS ####################################### + logging.info("Iteration of all protection jobs is complete") + print("Iteration of all protection jobs is complete") +######################### BEGIN: OPEN TICKETS FOR POPULATED PAUSED JOBS ################################## + + # This block of code is duplicate logic from above, the populatedPausedJobs array should not contain exempt jobs, we already checked for that. - CC 20230928 + +# if debug: +# print("Exempt jobs:\n{0}".format(exemptJobs)) +# +# for job in populatedPausedJobs: +# isJobExempt = False +# +# for entry in exemptJobs: +# parent = entry[0] +# pattern = entry[1] +# +# if parent == job['parentSourceId']: +# if re.search(pattern, job['name'].lower()): +# isJobExempt = True +# break +# +# if isJobExempt: +# continue +# else: + + logging.info("Opening tickets for paused jobs that contain VM objects") + for job in populatedPausedJobs: + if not excludeTickets: + subject = "Backup job " + job['name'] + " is paused" + message = "This backup job contains VMs and should not be paused per SLA. Either fix the issue and resume the job, exempt the VM(s) from backups, or decommission the VMs." + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + logging.info("Ticket {0} created for {1}".format(incident['result']['number'],job['name'])) + tickets.append("Ticket {0} created for {1}".format(incident['result']['number'],job['name'])) + else: + jobExemptions.append(job['name']) +######################### END: OPEN TICKETS FOR POPULATED PAUSED JOBS ################################## + +########################### END: JOB CENTRIC WORK ######################### +############################## BEGIN: IDENTIFY UNPROTECTED VMS ################################# + # RFE: 002 + # Open the list of documented exceptions, in the long term this may be in the ServiceNow CMDB + # if it is, we would have to look it up using the SNOW API + with open("./vars/exemptions.yml", "r") as exemptionData: + try: + exemptionData = yaml.load(exemptionData, Loader=yaml.FullLoader) + except: + print("Unable to load exemptions file.") + + exemptions = [] + + for i in exemptionData: + for e in exemptionData[i]['vms']: + #exemptions.append([exemptionData[i]['id'],e.lower()]) + exemptions.append([exemptionData[i]['id'],e]) + + # Find protected / unprotected vms + logging.info("Iterating through all vmObjects found under sources registered to {0}".format(args.cluster)) + print("Iterating through all vmObjects found under sources registered to {0}".format(args.cluster)) + for vm in vmObjects: + # We don't need to monitor VMs that are marked as a template VM + if vm['environment'] == "kVMware": + if 'isVmTemplate' in vm['vmWareProtectionSource']: + if vm['vmWareProtectionSource']['isVmTemplate'] == True: + continue + + # Assume all VM objects are not protected until we prove otherwise + isProtected = False + + # Use flag to determine if VM was found or not + for pVM in protectedObjects: + if vm['name'] == pVM['protectionSource']['name']: + isProtected = True + protectedVM.append(vm) + break + + # The Azure naming convention is different from the vmware naming convention, we need to normalize the names for sharepoint loookups + # and exemption lookups + + # 4/22/2025 + # Do we have to lookup the names to quantify the domain anymore? + # Will need a sample dataset from Cohesity call and SNOW lookups to determine. + if vm['environment'] == "kAzure": + + # Azure VMs usually follow the naming convetion of vm-myserver.domain.com + # so we split on '-' and use the second part. + if "-" in vm['name']: + nameParts = vm['name'].split("-") + + # SharePoint + #hostname= cmdb.find_VM(nameParts[1]) + + # ServiceNow + try: + cmdbData=cmdb.getCMDBItemByHostName(nameParts[1]) + cmdbData=cmdbData[0] + except: + try: + print("INFO: possible name mismatch, searching via full name") + cmdbData = cmdb.getCMDBItemByHostName(vm['name']) + cmdbData=cmdbData[0] + except: + print(vm['name'] + " not found") + undocumentedVM.append(vm['name']) + continue + + #if nameParts[1] == hostname: + if nameParts[1] != cmdbData['host_name']: + + print("INFO: possible name mismatch, searching via full name") + + # Data wasn't found, search for the full vm name + # SharePoint + #hostname = cmdb.find_VM(vm['name']) + + # ServiceNow + cmdbData = cmdb.getCMDBItemByHostName(vm['name']) + cmdbData=cmdbData[0] + + # 2024-04-23: This double lookup was created to handle an edge case where there was a + # '-' in the hostname. The VM has since been decomissioned but we will + # leave the logic in place but 'continue' the loop and write out a warning. + #if cmdbData['host_name'] == "vm-lcsdev1-1": + # # Sharepoint + # #hostname = cmdb.get_Node("vm-lcsdev1dev.centralus.cloudapp.azure.com") + + # # ServiceNow + # cmdbData = cmdb.getCMDBItemByFQDN('vm-lcsdev1dev.centralus.cloudapp.azure.com') + # cmdbData=cmdbData[0] + + else: + # SharePoint + # hostname = cmdb.find_VM(vm['name']) + + # ServiceNow + try: + cmdbData = cmdb.getCMDBItemByFQDN(vm['name']) + cmdbData=cmdbData[0] + except: + print(vm['name'] + " not found") + undocumentedVM.append(vm['name']) + continue + + vm.update({"name": cmdbData['fqdn']}) + + # This part needs some significant improvement on handling the exceptions. Ideally we would want to ensure the + # hostname that is excluded belongs to the same parent in the exemption file and in Cohesity. + if not isProtected: + isExempted = False + for entry in exemptions: + parent = entry[0] + pattern = entry[1] + if parent == vm['parentId']: + if re.search(pattern, vm['name'].lower()): + isExempted = True + vmExemptions.append(vm['name']) + break + else: + continue + if isExempted == False: + unprotectedVM.append(vm) + +############################## END: IDENTIFY UNPROTECTED VMS ################################# + +###################### BEGIN: OPEN TICKETS FOR UNPROTECTED & UNEXEMPTED VMS ######################## + +# Setup an array to hold unique AppNames +unProtectedApps = [] +for vm in unprotectedVM: + + vcenterSource = cluster.GetFilteredRequest("/public/protectionSources", "?id=" + str(vm['parentId'])) + vcenterName = vcenterSource[0]['protectionSource']['name'].split(".")[0] + + if args.type == "kAzure": + if vcenterName == "437b2bfa-850e-4464-b6c2-38a68cda7c69": + vcenterName = "prd01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-PRD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-PRD": + jobPolicy=pol['id'] + + elif vcenterName == "76297098-764c-43de-8525-c9fda1b237be": + vcenterName = "npd01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NPD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NPD": + jobPolicy=pol['id'] + + elif vcenterName == "e53aa0c7-824d-40a2-b420-4ab77b1051d2": + vcenterName = "infra01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-INFRA") + for pol in policyData: + if pol['name'] == "ITD-Bronze-INFRA": + jobPolicy=pol['id'] + + elif vcenterName == "cb39dbef-0ecf-434d-a8b9-444cef8f390a": + vcenterName = "cares01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-CARES") + for pol in policyData: + if pol['name'] == "ITD-Bronze-CARES": + jobPolicy=pol['id'] + + elif vcenterName == "54048952-c2b2-4c65-ab44-157750caa8e6": + vcenterName = "NDIT-PaaS" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NDIT-PaaS") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NDIT-PaaS": + jobPolicy=pol['id'] + + # Trim off .nd.gov from the name + vcenterName = vcenterName.split(".")[0] + + #RFE 001: CMDB reference lookups will need to be updated to the SeriveNow CMDB once it is ready for production, this is slated for October 2022. + # SharePoint + #cmdbRecord = cmdb.get_Node(vm['name']) + + # Commenting this out & setting it to null because the SeriveNow logic already exists below + # ServiceNow + try: + cmdbRecord = cmdb.getCMDBItemByFQDN(vm['name']) + cmdbRecord = cmdbRecord[0] + inSnow = True + except: + inSnow = False + + if not inSnow: + + # 2024-04-23: Sharepoint is gone, the primary source is ServiceNow & the code has been + # adjusted accordingly + #if len(cmdbRecord) == 0: + # Handle cases where the record doesn't exist in Sharepoint yet, but might be going through + # the build process in ServiceNow + + + #try: + # print("Trying to find: {}".format(vm['name'])) + # cmdbData = ticketSystem.getCMDBItemByFQDN(vm['name']) + # print("ServiceNow: {0}, vmware: {1}".format(cmdbData[0]['fqdn'],vm['name'])) + # if cmdbData[0]['fqdn'] == vm['name']: + # print("Found in Snow CMDB") + # inSnow = True + #except: + # inSnow = False + + # Part of old logic + #if not excludeTickets and (inSnow == False): + + # Open a ticket for unprotected VMs that are not in the CMDB + if not excludeTickets: + undocumentedVM.append(vm['name'] + " on " + vcenterName) + + #12/11/2023: Removed tickets for undocumented VMs until the CMDB is fixed. + #2024-04-23: Resume tickets for undocumented VMs + subject = "Backup job for " + vm['name'] + " on " + vcenterName + " was not found." + message = "This VM was not found in the CMDB and is not being backed up.\nInvestigate why the object is not documented in the vmware list, and not being backed up. If necessary have the backup admins exclude the item in the exemptions.yml file" + + #12/11/2023: Removed tickets for undocumented VMs until the CMDB is fixed. + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + print("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + tickets.append("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + + continue + else: + continue + # There is a record for the VM in the CMDB so lets construct the appropriate protection group name + else: + + #RFE 001: CMDB reference lookups will need to be updated to the SeriveNow CMDB once it is ready for production, this is slated for October 2022. + # Sharepoint + #vmAppName = cmdb.get_AppName(cmdbRecord[0]['AppNameId']) + #vmEnvironment = cmdbRecord[0]['Environment'] + + # ServiceNow + vmAppName = cmdbRecord['u_nd_application_svc']['name'] + vmEnvironment = cmdbRecord['environment'] + + if args.type == "kVMware": + if vmEnvironment == "Production": + jobName = vmAppName + "@" + "PRD-" + vcenterName + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-PRD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-PRD": + jobPolicy=pol['id'] + #jobPolicy="4847477517838800:1610060943809:72255100" + + elif vmEnvironment == "Test": + jobName = vmAppName + "@" + "NPD-" + vcenterName + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NPD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NPD": + jobPolicy=pol['id'] + #jobPolicy="4847477517838800:1610060943809:72255060" + elif args.type == "kAzure": + jobName = "{0}@{1}".format(vmAppName, vcenterName) + + # Don't add the job name to the unprotectedApps array more than once + if jobName in unProtectedApps: + continue + else: + # Verify that the job does not already exist in Cohesity + verify = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + jobName ) + + if len(verify) > 0: + for record in verify: + if record['name'] != jobName: + jobExists = False + else: + jobExists = True + break + + if (len(verify) == 0) or (jobExists == False): + unProtectedApps.append(jobName) + + if args.type == "kVMware": + tagId = cluster.GetVcenterTagId(vcenterSource, vmAppName) + + if vmEnvironment == "Test": + excludeTag = cluster.GetVcenterTagId(vcenterSource, "Production") + + elif vmEnvironment == "Production": + excludeTag = cluster.GetVcenterTagId(vcenterSource, "Test") + + if tagId is not None: + confirm = "yes" + #confirm = input("About to create a protection job for {0}. Are you sure? [yes|no]".format(jobName)) + if (confirm.lower() == "yes") and (not excludeTickets): + print("Creating standard change request for {0}.".format(jobName)) + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Systems Platform - Systems", "Backup/Restore", "Automated Change - Create protection job {0}".format(jobName), "Initial protection group creation.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.reviewStandardChange(changeSysID) + + resp = cluster.CreateVMProtectionJob(jobName, vcenterSource[0]['protectionSource']['id'], tagId, excludeTag,jobPolicy) + postChangeNotes = resp.text + + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + print("Job {} created, {} complete".format(jobName, changeID['result']['number']['value'])) + tickets.append("Change {} created for {}".format(changeID['result']['number']['value'],jobName)) + + if args.type == "kAzure": + print("Create backup job for job {0}".format(jobName)) + print("Looking up Tag ID for {0}".format(vmAppName)) + tagId = cluster.GetAzureTagId(vcenterSource, vmAppName) + + if (tagId is not None) and (not excludeTickets): + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Systems Platforms - Systems", "Backup/Restore", "Automated Change - Create protection job {0}".format(jobName), "Initial protection group creation.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.reviewStandardChange(changeSysID) + + resp = cluster.CreateAZProtectionJob(jobName, vcenterSource[0]['protectionSource']['id'], tagId) + postChangeNotes = resp.text + + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + + print("Created {0} for {1}".format(changeID,jobName)) + tickets.append("Ticket {0} created for {1}".format(changeID['result']['number']['value'],jobName)) + + else: + print("Tag not found in Azure: {}".format(vmAppName)) + subject = "Tag {} was not found in the {} virtualization platform".format(vmAppName, args.type) + message = "The application name tag {0} used to create backup job {1} was not found. The ApplicationName tag for {2} must be a case sensitive match with the Sharepoint record.".format(vmAppName, jobName, vm['name']) + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + tickets.append("Ticket {} created for {}".format(incident['result']['number'],vmAppName)) + + else: + if not excludeTickets: + subject = "Backup job for " + vm['name'] + " was not found in " + jobName + "." + message = "Assign ticket to vmWare or Storage to investigate vm tagging issues." + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + print("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + tickets.append("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + undocumentedVM.append(vm['name']) + +#itdTeamsMessage.text("Empty Jobs: {0}\nPopulated Jobs: {1}\nPopulated Paused Jobs: {2}\nUnprotected VMs: {3}".format(str(len(emptyJobs)),str(len(populatedJobs)),str(len(populatedPausedJobs)),str(len(unprotectedVM)))) +#itdTeamsMessage.send() +body = "" + +body = body + "Job Summary:" +data = str(len(populatedJobs)) if len(populatedJobs) > 0 else str(0) +body = body + "\n\tPopulated Jobs: " + data + +data = str(len(populatedPausedJobs)) if len(populatedPausedJobs) > 0 else str(0) +body = body + "\n\tPaused Jobs: " + data + +data = str(len(emptyJobs)) if len(emptyJobs) > 0 else str(0) +body = body + "\n\tEmpty Jobs: " + data + +data = str(len(unProtectedApps)) if len(unProtectedApps) > 0 else str(0) +body = body + "\n\tUnprotected Apps: " + data + +body = body + "\n\nVM Summary:" +data = str(len(unprotectedVM)) if len(unprotectedVM) > 0 else str(0) +body = body + "\n\tUnprotected VMs: " + data + +data = str(len(undocumentedVM)) if len(undocumentedVM) > 0 else str(0) +body = body + "\n\tUndocumented VMs: " + data + +body = body + "\n\nTickets Created:" +for i in tickets: + body = body + "\n\t" + str(i) + +body = body + "\n\nDetails:" +body = body + "\n\tEmpty Jobs: " + +jobs=[] +for i in emptyJobs: + jobs.append(i['name']) +jobs.sort() +for i in jobs: + body = body + "\n\t\t" + str(i) + +jobs=[] +body = body + "\n\tPaused Jobs:" +for i in populatedPausedJobs: + jobs.append(i['name']) + +jobs.sort() +for i in jobs: + body = body + "\n\t\t" + str(i) + +body = body + "\n\tUnprotected Apps:" +unProtectedApps.sort() +for i in unProtectedApps: + body = body + "\n\t\t" + str(i) + +# The unprotededVM array is a dict of vm objects, we only need the vm name here +vms = [] +body = body + "\n\tUnprotected VMs: " +for i in unprotectedVM: + vms.append(i['name']) + +vms.sort() +for i in vms: + body = body + "\n\t\t" + str(i) +# End sorting of unprotectedVM + +undocumentedVM.sort() +body = body + "\n\tUndocumented Deployed VMs:" +for i in undocumentedVM: + body = body + "\n\t\t" + str(i) + +body = body + "\n\tDeployed Backup Exempt VMs:" +vmExemptions.sort() +for i in vmExemptions: + body = body + "\n\t\t" + str(i) + +body = body + "\n\tDeployed Backup Exempt Apps:" +jobExemptions.sort() +for i in jobExemptions: + body = body + "\n\t\t" + str(i) + +SendEmail(body, args.cluster) + +if debug: + print(body) +else: + dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Provisioning', 'Platform': 'Python-dailyProtectionReview.py', 'Units': 120}) diff --git a/_NDGOV_CS/ITD.Cohesity/dailyErrors.py b/_NDGOV_CS/ITD.Cohesity/dailyErrors.py new file mode 100644 index 0000000..f65948b --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/dailyErrors.py @@ -0,0 +1,217 @@ +#!/usr/bin/python +#-------------------------------------------------------------------------------------------------------------# +# Author: Cliff Cogdill +# Description: Gather the protection runs from the last 24 hours, limited to 5000 jobs, and seperate them into +# Running, Canceled, Failures, warning, hold, and missed. +# If the protection group is empty pause it. +# If there are failures in the protection job, open a ServiceNow ticket. +# Send out a summary of the previous 24 hour run +# +# +#-------------------------------------------------------------------------------------------------------------# +import sys,argparse,json,time,smtplib +from email.message import EmailMessage +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import serviceNowAPI as snow +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--job', '-j', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + parser.add_argument('--debugMode', '-d', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 dailyErrors.py -c cluster1.domain.tld" ) + print("\t -c FQDN of Cohesity cluster address") + print("\t -h Prints this help message") + +def SendEmail(body, cluster): + if debugMode: + recipients = ['cecogdill@nd.gov'] + else: + recipients = ['zmeier@nd.gov', 'cecogdill@nd.gov'] + + email = EmailMessage() + email['Subject'] = "Cohesity Job Status for {0}".format(cluster) + email['From'] = "No-Reply@nd.gov" + email['To'] = ", ".join(recipients) + email.set_content(body) + + with smtplib.SMTP('apprelay.nd.gov') as smtp: + smtp.send_message(email) + + print("Sent email") + +# Define variables +args = GetArgs() + +if args.debugMode: + debugMode = True +else: + debugMode = False + +# Check for arguments and act accoringly +if args.help: + PrintHelp() + exit(1) + +# Establish a connection to ServiceNow +if debugMode: + ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") +else: + ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +# Establish a connection to Cohesity +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Get yesterday's start time in unixEpoch: +prevWindow = cluster.GetRelativeTimestamp(-1, 17, 0, 0) + +# Debug Output +if args.debugMode: + print("\nPulling backup jobs from {}\n".format(prevWindow)) + +# Pull a list of protection runs from yesterday's backup window. +jobStatus = cluster.GetFilteredRequest("/public/protectionRuns","?startTimeUsecs=" + str(prevWindow) + "&numRuns=5000") + +#Define the arrays we will use to sort the protectionRuns +running = [] +cancel = [] +failures = [] +failControl = [] +warnings = [] +holds = [] +missed = [] +tickets = [] + +# Examine and sort the jobs by type status +for job in jobStatus: + + # Debug Output + if args.debugMode: + print("Status of {0}: {1}\n".format(job['jobName'],job['backupRun']['status'])) + + # Look for failures + if job['backupRun']['status'] == "kRunning": + running.append(job) + elif job['backupRun']['status'] == "kCanceling" or job['backupRun']['status'] == "kCanceled": + cancel.append(job) + elif job['backupRun']['status'] == "kFailure": + if job['jobName'] + job['backupRun']['error'] in failControl: + continue + else: + failControl.append(job['jobName'] + job['backupRun']['error']) + failures.append(job) + elif job['backupRun']['status'] == "kWarning": + warnings.append(job) + elif job['backupRun']['status'] == "kOnHold": + holds.append(job) + elif job['backupRun']['status'] == "kMissed": + missed.append(job) + else: + continue + +# Start formatting the email output into the 'body' variable. +body = "Running: " + str(len(running)) +for entry in running: + message = "\n\t " + entry['jobName'] + body = body + message + +body = body + "\nCanceled: " + str(len(cancel)) +for entry in cancel: + message = "\n\t " + entry['jobName'] + body = body + message + +body = body + "\nFailures: " + str(len(failures)) +for entry in failures: + retired = False + + # Create the message entry + message = "\n\t " + entry['jobName'] + + if entry['jobName'] == 'NDPERS-Applications@physical': + continue + + if 'error' in entry['backupRun']: + errorMessage = entry['backupRun']['error'] + + # We know there are empty protection jobs but we don't need to create a ticket on them; instead lets pause them and then + # add logic to the daily backup audit script (dailyProtectionReview.py) to check the paused jobs for VMs and take action + # if needed + if errorMessage == "Cannot find any eligible backup source for this run": + errorMessage = "Protection group was empty, future runs will be paused by the dailyProtectionReview.py script" + #No need to continue and create a ticket so lets go to the next item + continue + + for source in entry['backupRun']['sourceBackupStatus']: + + if 'error' in source: + #errorMessage = "Details:" + + # Clean up Cohesitys error a bit + if "Exceeded the maximum number of permitted snapshots" in source['error']: + errorMessage = "\n\t\t" + errorMessage + source['source']['name'] + ":\n\t\t\tAn error occurred while saving \ + the snapshot: Exceeded the maximum number of permitted snapshots. Check whether or not snapshots on \ + these objects are allowed in the VM properties. If snapshots are not allowed, ensure the server is \ + exempted from backups according to NDIT Backup Exemption procedures.\n" + else: + errorMessage = "\n\t\t" + source['source']['name'] + ":\n\t\t\t" + source['error'] + + + # Retired in ServiceNow + this_vm = source['source']['name'] + cmdbRecord = ticketSystem.getCMDBItemByFQDN(this_vm) + + # ServiceNow returns the index as string object so we either have to convert it to int or the check to str + if len(cmdbRecord) > 0: + if int(cmdbRecord[0]['operational_status']) == 6: + retired = True + + # Create the incident based off the error message in the job + incident = ticketSystem.submitTicket("svccohesityadm", "Backup Error for: " + entry['jobName'], errorMessage) + incidentID = incident['result']['sys_id'] + tickets.append(incident['result']['number']) + + if '@SQL' in entry['jobName'] and retired != True: + # Assign the incident to storage + ticketSystem.assignTicketToGroup(incidentID, 'NDIT-Database') + + else: + # Assign the incident to storage + ticketSystem.assignTicketToGroup(incidentID, 'NDIT-Computer Systems Storage') + + message = message + errorMessage + body = body + message + +body = body + "\nWarning: " + str(len(warnings)) +for entry in warnings: + message = "\n\t " + entry['jobName'] + body = body + message + +body = body + "\nHold: " + str(len(holds)) +for entry in holds: + message = "\n\t " + entry['jobName'] + body = body + message + +body = body + "\nMissed: " + str(len(missed)) +for entry in missed: + message = "\n\t " + entry['jobName'] + body = body + message + +body = body + "\nTickets: " + str(len(tickets)) + "\n\t Instance: " + ticketSystem.snInstance +for t in tickets: + message = "\n\t\t" + t + body = body + message + +# Send the email to the list of recipients in the local SendEmail function +SendEmail(body, args.cluster) +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-dailyErrors.py', 'Units': 60}) diff --git a/_NDGOV_CS/ITD.Cohesity/dailyProtectionReview.py b/_NDGOV_CS/ITD.Cohesity/dailyProtectionReview.py new file mode 100644 index 0000000..27329fa --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/dailyProtectionReview.py @@ -0,0 +1,646 @@ +#!/usr/bin/python +#-------------------------------------------------------------------------------------------------# +# Author: Cliff Cogdill +# Description: This script accomplishes a few things: +# - Reviews all assets in the CMDB to determine if they have been setup in backups. +# - If not, identify them and send create a ticket for investigation. +# - Reviews paused protection jobs to determine if the job is still empty. +# - If not empty, resume the job. +# - Send summary report of unprotected servers and VM jobs to the storage team. +# ------------------------------------------------------------------------------------------------# + +import sys,argparse,json,time,yaml,re,smtplib +from email.message import EmailMessage +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import sharePointAPI as sharePoint +import automationsAPI as dashboard +#import serviceNowAPI as snow +import nditServiceNow as snow +import logging +#import pymsteams + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--debug', '-d', action='store_true') + parser.add_argument('--excludeTickets', '-x', action='store_true') + parser.add_argument('--refresh', '-r', action='store_true') + parser.add_argument('--type', '-t', type=str, action='store') + parser.add_argument('--vCenter', '-v', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def SendEmail(body, cluster): + if debug: + recipients = ['itbackups@nd.gov'] + else: + recipients = ['zmeier@nd.gov', 'cecogdill@nd.gov','khellman@nd.gov','mlaverdure@nd.gov','ndheck@nd.gov'] + + email = EmailMessage() + email['Subject'] = "Backup Review for {0}".format(cluster) + email['From'] = "No-Reply@nd.gov" + email['To'] = ", ".join(recipients) + email.set_content(body) + + with smtplib.SMTP('apprelay.nd.gov') as smtp: + smtp.send_message(email) + + print("Sent email") + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 protectedItems.py -c cluster1.domain.tld [ -v vCenter.domain.tld ] [ -j protectionJobName ]") + print("\t -d debug: execute in debug mode to expand summary and do not open tickets") + print("\t -x excludeTickets: run against prod serivce now but do not open tickets or changes") + print("\t -r refresh: force source refresh in debug mode") + print("\t -c FQDN of Cohesity cluster address") + print("\t -t type of protection source") + print("\t -h Prints this help message") + +#itdTeamsMessage = pymsteams.connectorcard("https://ndgov.webhook.office.com/webhookb2/aad89030-8f69-4a4d-a853-c882cbb01a10@2dea0464-da51-4a88-bae2-b3db94bc0c54/IncomingWebhook/d3c07921419c4920810d0c32558c05e3/edcc1502-1ff0-4c3e-9fe2-1ce3f9f7981a") + +args = GetArgs() + +if args.help: + PrintHelp() + exit() + +logging.basicConfig(filename="log/" + args.cluster + '.log', filemode='w', format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %I:%M:%S %p', level=logging.DEBUG) + +# Define empty lists that will hold JSON dictionaries +vmObjects = [] +protectedObjects = [] +vCenters = [] +protectedVM = [] +unprotectedVM = [] +undocumentedVM = [] +populatedJobs = [] +populatedPausedJobs = [] +emptyJobs = [] + +# Default to the main cluster on premise if the cluster argument was not specified +if not args.cluster: + args.cluster = "itdmdndpc01.nd.gov" + args.type = "kVMware" + +if not args.type: + args.type = "kVMware" + +if args.cluster == "itdazdpc01.nd.gov": + args.type = "kAzure" + +if args.cluster == "itdazdpc02.nd.gov": + args.type = "kAzure" + +logging.info("Creating cluster object for {0} with type {1}".format(args.cluster, args.type)) + +# Setup the token for cluster API usage +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Lookup the AppNames and vCenter for unprotected VMs +#logging.info("Createing cmdb object for SharePoint list") +#cmdb = sharePoint.API() + +# When true, tickets will only be created in ServiceNow dev and JSON output may be expanded to stdout +if args.debug: + debug = True +else: + debug = False + +if args.excludeTickets: + excludeTickets = True +else: + excludeTickets = False + +# Create the connection to ServiceNow +logging.info("Creating ticketSystem object for ServiceNow") + +if debug: + ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") +else: + ticketSystem = snow.SnowAPI("northdakota.service-now.com") + + + +if args.type == "kPhysical": + physicalJobs = cluster.GetPhysicalJobs() + sys.exit("Warning: Type not implmented for this script.") + +elif args.type == "kSQL": + sys.exit("Warning: Type not implmented for this script.") + +elif args.type == "kAzure": +# Get all registered subscription sources so we can use the source ids for other REST calls + logging.info("Collecting all registered Azure sources") + nodes = cluster.GetAZsources() + + # Iterate through all the Azure subscriptions to create one large dataset for all VMs + logging.info("Creating dataset for all VMs in our Azure subscriptions") + logging.info("Creating dataset for all protected VMs in our Azure subscriptions") + for node in nodes: + hypervisorId = node['protectionSource']['id'] + + #Refresh the sources so we ensure we are getting valid information + if debug: + print("Debug enabled, not refreshing source use -r option to override") + else: + cluster.RefreshSource(node['protectionSource']['id']) + + if args.refresh: + cluster.RefreshSource(node['protectionSource']['id']) + + myObjects = cluster.GetAZObjects(hypervisorId) + myProtectedObjects = cluster.GetProtectedAZobjects(hypervisorId) + + # Combine all VM objects into one dictionary + for val in myObjects: + vmObjects.append(val) + + # Combine all protected objects into one dictionary + for val in myProtectedObjects: + protectedObjects.append(val) + + # Get all the native snapshot protection jobs that exist in the cluster + logging.info("Gathering all current protection jobs from {0}".format(args.cluster)) + sourceJobs = cluster.GetAZNativeJobs() + +elif args.type == "kVMware": + # Get all registered vCenter sources so we can use the source ids for other REST calls + logging.info("Collecting all registered vmWare sources") + nodes = cluster.GetVMsources() + + # Iterate through all the vCenter servers to create one large dataset for all VMs + logging.info("Creating dataset for all VMs in our Azure subscriptions") + logging.info("Creating dataset for all protected VMs in our Azure subscriptions") + for node in nodes: + hypervisorId = node['protectionSource']['id'] + + #Refresh the sources so we ensure we are getting valid information + cluster.RefreshSource(node['protectionSource']['id']) + + myObjects = cluster.GetVMObjects(hypervisorId) + myProtectedObjects = cluster.GetProtectedVMobjects(hypervisorId) + + # Combine all VM objects into one dictionary + for val in myObjects: + vmObjects.append(val) + + # Combine all protected objects into one dictionary + for val in myProtectedObjects: + protectedObjects.append(val) + + # At this point we have two sets of data + # 1. All vms objects whether they are protected or not ( vmObjects ) + # 2. All protected vm objects ( protectedObjects ) + + # Get all the protection jobs that exist for vmware in the cluster + logging.info("Gathering all current protection jobs from {0}".format(args.cluster)) + sourceJobs = cluster.GetVMjobs() + +if args.type == "kVMware" or args.type == "kAzure": + +############################## BEGIN: IDENTIFY EMPTY & POPULATE PAUSED JOBS ####################################### + # Loop through the sourceJobs to see if they show up in at least once in the list of protected objects. + # if they don't show up, we can assume the job is created but empty, which is usually the case for + # placeholder VMs + + # In certain circumstances, jobs can be defined but exempt from normal processing. These jobs are normally used from time to time for POC work and do not necessarily need to be protected, here we will load them into the exempt jobs array from the exceptions.yml file. + logging.info("Opening exemptions file: vars/exemptions.yml") + with open("./vars/exemptions.yml", "r") as exemptionJobData: + try: + exemptionJobData = yaml.load(exemptionJobData, Loader=yaml.FullLoader) + except: + print("Unable to load exemptions file.") + + exemptJobs = [] + + logging.info("Parsing exemptions YAML") + for i in exemptionJobData: + for e in exemptionJobData[i]['jobs']: + #exemptJobs.append(e.lower()) + exemptJobs.append([exemptionJobData[i]['id'],e.lower()]) + + # Loop through all the jobs for + logging.info("Iterating through all protection jobs") + for sourceJob in sourceJobs: + + #Set default control variables for each job + isJobExempt = False + isJobEmpty = True + + # The REST GetVMjobs function returns unfiltered jobs, so lets get rid of the deleted ones + if 'isDeleted' in sourceJob: + if sourceJob['isDeleted'] == True: + logging.info("--Job {0} is marked for deletion, skipping review".format(sourceJob['name'])) + continue + + # Look through the exemptJobs listing + for entry in exemptJobs: + parent = entry[0] + pattern = entry[1] + + if parent == sourceJob['parentSourceId']: + if re.search(pattern, sourceJob['name'].lower()): + isJobExempt = True + break + + if isJobExempt == True: + if debug == True: + logging.info("--Job {0} has been exempt from backups, skipping review".format(sourceJob['name'])) + print("Job {0} is exempt from tickets".format(sourceJob['name'])) + continue + + + # The protection jobs only show tags, they do not show VM ojbects; therefore, to determine if the job is still valid, we have to iterate through all protected objects to see if the job name shows up or not. If it does not show up, then it is assumed to be empty and paused to prevent backup errors. Also, there is usually only one job listed per protected VM; however, there could be cases where a VM is in two or more jobs so we need to check each job listed. + # Sample dataset can be seen by using the following url: + # https://itdmdndpc01.nd.gov/irisservices/api/v1/public/protectionSources/protectedObjects?environment=kVMware&id=3156 + logging.info("--Iterating through all protected objects to verify if job {0} is empty".format(sourceJob['name'])) + for item in protectedObjects: + for pJob in item['protectionJobs']: + if pJob['name'] == sourceJob['name']: + isJobEmpty = False + continue + + # Seperate empty from non-empty jobs + if isJobEmpty: + logging.info("--{0} is empty, pausing future runs".format(sourceJob['name'])) + emptyJobs.append(sourceJob) + # Pause the job so we don't generate erroneous errors. + cluster.PauseJob(sourceJob['id']) + + else: + # The job is not empty, lets check to see if it is paused so we can create an alert. + + # First we have to check if the isPaused key exists, if it has never been set, it will not. + if 'isPaused' in sourceJob: + # Now we check to see if isPaused is set to True + if sourceJob['isPaused']: + logging.info("----{0} is paused but contains VM objects, adding to populatedPausedJobs dataset".format(sourceJob['name'])) + populatedPausedJobs.append(sourceJob) + # isPaused might be defined but it is set to False + else: + populatedJobs.append(sourceJob) + + # If the job has never been paused, isPaused may not be defined + else: + populatedJobs.append(sourceJob) + +############################## END: IDENTIFY EMPTY & POPULATE JOBS ####################################### + logging.info("Iteration of all protection jobs is complete") +######################### BEGIN: OPEN TICKETS FOR POPULATED PAUSED JOBS ################################## + + # This block of code is duplicate logic from above, the populatedPausedJobs array should not contain exempt jobs, we already checked for that. - CC 20230928 + +# if debug: +# print("Exempt jobs:\n{0}".format(exemptJobs)) +# +# for job in populatedPausedJobs: +# isJobExempt = False +# +# for entry in exemptJobs: +# parent = entry[0] +# pattern = entry[1] +# +# if parent == job['parentSourceId']: +# if re.search(pattern, job['name'].lower()): +# isJobExempt = True +# break +# +# if isJobExempt: +# continue +# else: + + logging.info("Opening tickets for paused jobs that contain VM objects") + for job in populatedPausedJobs: + if not excludeTickets: + subject = "Backup job " + job['name'] + " is paused" + message = "This backup job contains VMs and should not be paused per SLA. Either fix the issue and resume the job, exempt the VM(s) from backups, or decommission the VMs." + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + logging.info("--{0} created for {1}".format(incident['result']['number'],job['name'])) +######################### END: OPEN TICKETS FOR POPULATED PAUSED JOBS ################################## + +############################## BEGIN: IDENTIFY UNPROTECTED VMS ################################# + # RFE: 002 + # Open the list of documented exceptions, in the long term this may be in the ServiceNow CMDB + # if it is, we would have to look it up using the SNOW API + with open("./vars/exemptions.yml", "r") as exemptionData: + try: + exemptionData = yaml.load(exemptionData, Loader=yaml.FullLoader) + except: + print("Unable to load exemptions file.") + + exemptions = [] + + for i in exemptionData: + for e in exemptionData[i]['vms']: + #exemptions.append([exemptionData[i]['id'],e.lower()]) + exemptions.append([exemptionData[i]['id'],e]) + + # Find protected / unprotected vms + logging.info("Iterating through all vmObjects found under sources registered to {0}".format(args.cluster)) + for vm in vmObjects: + # We don't need to monitor VMs that are marked as a template VM + if vm['environment'] == "kVMware": + if 'isVmTemplate' in vm['vmWareProtectionSource']: + if vm['vmWareProtectionSource']['isVmTemplate'] == True: + continue + + # Assume all VM objects are not protected until we prove otherwise + isProtected = False + + # Use flag to determine if VM was found or not + for pVM in protectedObjects: + if vm['name'] == pVM['protectionSource']['name']: + isProtected = True + protectedVM.append(vm) + break + + # The Azure naming convention is different from the vmware naming convention, we need to normalize the names for sharepoint loookups + # and exemption lookups + + # SharePoint Removal + + #if vm['environment'] == "kAzure": + # if "-" in vm['name']: + # nameParts = vm['name'].split("-") + # hostname= cmdb.find_VM(nameParts[1]) + + # if nameParts[1] == hostname: + # hostname = cmdb.find_VM(vm['name']) + + # if hostname == "vm-lcsdev1-1": + # hostname = cmdb.get_Node("vm-lcsdev1dev.centralus.cloudapp.azure.com") + # else: + # hostname = cmdb.find_VM(vm['name']) + + # vm.update({"name": hostname}) + + # This part needs some significant improvement on handling the exceptions. Ideally we would want to ensure the + # hostname that is excluded belongs to the same parent in the exemption file and in Cohesity. + if not isProtected: + isExempted = False + for entry in exemptions: + parent = entry[0] + pattern = entry[1] + if parent == vm['parentId']: + if re.search(pattern, vm['name'].lower()): + isExempted = True + break + else: + continue + if isExempted == False: + unprotectedVM.append(vm) + +############################## END: IDENTIFY UNPROTECTED VMS ################################# + +###################### BEGIN: OPEN TICKETS FOR UNPROTECTED & UNEXEMPTED VMS ######################## + +# Setup an array to hold unique AppNames +unProtectedApps = [] +for vm in unprotectedVM: + #RFE 001: CMDB reference lookups will need to be updated to the SeriveNow CMDB once it is ready for production, this is slated for October 2022. + + ###### sharepoint ##### + #cmdbRecord = cmdb.get_Node(vm['name']) + + ###### ServiceNow ##### + cmdbRecord = ticketSystem.getCMDBItemByFQDN(vm['name']) + + vcenterSource = cluster.GetFilteredRequest("/public/protectionSources", "?id=" + str(vm['parentId'])) + vcenterName = vcenterSource[0]['protectionSource']['name'].split(".")[0] + + if args.type == "kAzure": + if vcenterName == "437b2bfa-850e-4464-b6c2-38a68cda7c69": + vcenterName = "prd01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-PRD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-PRD": + jobPolicy=pol['id'] + + elif vcenterName == "76297098-764c-43de-8525-c9fda1b237be": + vcenterName = "npd01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NPD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NPD": + jobPolicy=pol['id'] + + elif vcenterName == "e53aa0c7-824d-40a2-b420-4ab77b1051d2": + vcenterName = "infra01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-INFRA") + for pol in policyData: + if pol['name'] == "ITD-Bronze-INFRA": + jobPolicy=pol['id'] + + elif vcenterName == "cb39dbef-0ecf-434d-a8b9-444cef8f390a": + vcenterName = "cares01" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-CARES") + for pol in policyData: + if pol['name'] == "ITD-Bronze-CARES": + jobPolicy=pol['id'] + + elif vcenterName == "54048952-c2b2-4c65-ab44-157750caa8e6": + vcenterName = "NDIT-PaaS" + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NDIT-PaaS") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NDIT-PaaS": + jobPolicy=pol['id'] + + # Trim off .nd.gov from the name + vcenterName = vcenterName.split(".")[0] + + +########################################################################################################################## +# # This was part of the SharePoint & ServiceNow cutover. Since we already pull the snow record above now, we don't +# # need to try to look for it again. +# + if len(cmdbRecord) == 0: +# # Handle cases where the record doesn't exist in Sharepoitn yet, but might be going through +# # the build process in ServiceNow +# try: +# print("Trying to find: {}".format(vm['name'])) +# cmdbData = ticketSystem.getCMDBItemByFQDN(vm['name']) +# +# print("ServiceNow: {0}, vmware: {1}".format(cmdbData[0]['fqdn'],vm['name'])) +# +# if cmdbData[0]['fqdn'] == vm['name']: +# print("Found in Snow CMDB") +# inSnow = True +# except: +# inSnow = False +# +######################################################################################################################## + # Open a ticket for unprotected VMs that are not in the CMDB + if not excludeTickets: + undocumentedVM.append(vm['name'] + " on " + vcenterName) + + #12/11/2023: Removed tickets for undocumented VMs until the CMDB is fixed. + + print("Undocumented VM: {0} on {1}".format(vm['name'],vcenterName)) + print("Ticket suppressed") + + ''' + subject = "Backup job for " + vm['name'] + " on " + vcenterName + " was not found." + message = "This VM was not found in the CMDB and is not being backed up.\nInvestigate why the object is not documented in the vmware list, and not being backed up. If necessary have the backup admins exclude the item in the exemptions.yml file" + + 12/11/2023: Removed tickets for undocumented VMs until the CMDB is fixed. + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + jincidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + print("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + + ''' + continue + else: + continue + +######################################################################################################################## + + # There is a record for the VM in the CMDB so lets construct the appropriate protection group name + else: + #RFE 001: CMDB reference lookups will need to be updated to the SeriveNow CMDB once it is ready for production, this is slated for October 2022. + ###### SharePoint ##### + #vmAppName = cmdb.get_AppName(cmdbRecord[0]['AppNameId']) + #vmEnvironment = cmdbRecord[0]['Environment'] + + ###### ServiceNow ##### + vmAppName = cmdbRecord[0]['u_nd_application_svc']['name'] + vmEnvironment = cmdbRecord[0]['environment'] + + if args.type == "kVMware": + if vmEnvironment == "Production": + jobName = vmAppName + "@" + "PRD-" + vcenterName + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-PRD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-PRD": + jobPolicy=pol['id'] + #jobPolicy="4847477517838800:1610060943809:72255100" + + elif vmEnvironment == "Test": + jobName = vmAppName + "@" + "NPD-" + vcenterName + policyData = cluster.GetProtectionPolicyByName("ITD-Bronze-NPD") + for pol in policyData: + if pol['name'] == "ITD-Bronze-NPD": + jobPolicy=pol['id'] + #jobPolicy="4847477517838800:1610060943809:72255060" + elif args.type == "kAzure": + jobName = "{0}@{1}".format(vmAppName, vcenterName) + + # Don't add the job name to the unprotectedApps array more than once + if jobName in unProtectedApps: + continue + else: + # Verify that the job does not already exist in Cohesity + verify = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + jobName ) + + if len(verify) > 0: + for record in verify: + if record['name'] != jobName: + jobExists = False + else: + jobExists = True + break + + if (len(verify) == 0) or (jobExists == False): + unProtectedApps.append(jobName) + + if args.type == "kVMware": + tagId = cluster.GetVcenterTagId(vcenterSource, vmAppName) + + if vmEnvironment == "Test": + excludeTag = cluster.GetVcenterTagId(vcenterSource, "Production") + + elif vmEnvironment == "Production": + excludeTag = cluster.GetVcenterTagId(vcenterSource, "Test") + + if tagId is not None: + confirm = "yes" + #confirm = input("About to create a protection job for {0}. Are you sure? [yes|no]".format(jobName)) + if (confirm.lower() == "yes") and (not excludeTickets): + print("Creating standard change request for {0}.".format(jobName)) + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Systems Platform - Systems", "Backup/Restore", "Automated Change - Create protection job {0}".format(jobName), "Initial protection group creation.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.reviewStandardChange(changeSysID) + + resp = cluster.CreateVMProtectionJob(jobName, vcenterSource[0]['protectionSource']['id'], tagId, excludeTag,jobPolicy) + postChangeNotes = resp.text + + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + print("Job {} created, {} complete".format(jobName, changeID['result']['number']['value'])) + + if args.type == "kAzure": + print("Create backup job for job {0}".format(jobName)) + print("Looking up Tag ID for {0}".format(vmAppName)) + tagId = cluster.GetAzureTagId(vcenterSource, vmAppName) + + if (tagId is not None) and (not excludeTickets): + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Systems Platforms - Systems", "Backup/Restore", "Automated Change - Create protection job {0}".format(jobName), "Initial protection group creation.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.reviewStandardChange(changeSysID) + + resp = cluster.CreateAZProtectionJob(jobName, vcenterSource[0]['protectionSource']['id'], tagId) + postChangeNotes = resp.text + + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + + print("Created {0} for {1}".format(changeID,jobName)) + + else: + print("Tag not found in Azure: {}".format(vmAppName)) + subject = "Tag {} was not found in the {} virtualization platform".format(vmAppName, args.type) + message = "The application name tag {0} used to create backup job {1} was not found. The ApplicationName tag for {2} must be a case sensitive match with the Sharepoint record.".format(vmAppName, jobName, vm['name']) + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + + else: + if not excludeTickets: + subject = "Backup job for " + vm['name'] + " was not found in " + jobName + "." + message = "Assign ticket to vmWare or Storage to investigate vm tagging issues." + incident = ticketSystem.submitTicket("svccohesityadm", subject, message) + incidentID = incident['result']['sys_id'] + ticketSystem.assignTicketToGroup(incidentID, "NDIT-Cloud Platforms") + print("Ticket {} created for {}".format(incident['result']['number'], vm['name'])) + +#itdTeamsMessage.text("Empty Jobs: {0}\nPopulated Jobs: {1}\nPopulated Paused Jobs: {2}\nUnprotected VMs: {3}".format(str(len(emptyJobs)),str(len(populatedJobs)),str(len(populatedPausedJobs)),str(len(unprotectedVM)))) +#itdTeamsMessage.send() + +body = "Backup Jobs: " + str(len(populatedJobs)) +body = body + "\nPaused Jobs: " + str(len(populatedPausedJobs)) +body = body + "\nUnprotected VMs: " + str(len(undocumentedVM)) +for vm in undocumentedVM: + body = body + "\n\t" + vm +SendEmail(body, args.cluster) +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Provisioning', 'Platform': 'Python-dailyProtectionReview.py', 'Units': 120}) + +if debug: + array1=[] + print("Empty Jobs: " + str(len(emptyJobs))) + for value in emptyJobs: + print("\t" + value['name']) + print("Populated Jobs: " + str(len(populatedJobs))) + print("Paused Jobs: " + str(len(populatedPausedJobs))) + for value in populatedPausedJobs: + print("\t" + value['name']) + print("Unprotected VMs: " + str(len(unprotectedVM))) + for value in unprotectedVM: + array1.append(value['name'] + ", " + str(value['parentId'])) + print("Sorted Unprotected VMs") + array1.sort() + for i in array1: + print(str(i)) + + print("Unprotected Apps") + unProtectedApps.sort() + for i in unProtectedApps: + print(str(i)) diff --git a/_NDGOV_CS/ITD.Cohesity/diskAlerts.py b/_NDGOV_CS/ITD.Cohesity/diskAlerts.py new file mode 100644 index 0000000..000629a --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/diskAlerts.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +#-------------------------------------------------------------------------------------------------------------# +# Author: Cliff Cogdill +# Description: Review the logs for disk alerts and open a servicenow ticket if one exists. +# +# +#-------------------------------------------------------------------------------------------------------------# +import sys,argparse,json,time,smtplib +from email.message import EmailMessage +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import serviceNowAPI as snow +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--debugMode', '-d', action='store_true') + parser.add_argument('--days', '-t', type=int, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 diskAlerts.py -c cluster1.domain.tld" ) + print("\t -c FQDN of Cohesity cluster address") + print("\t -t time duration to look back in days") + print("\t -h Prints this help message") + +def SendEmail(body, cluster_name): + if debugMode: + recipients = ['cecogdill@nd.gov'] + else: + recipients = ['zmeier@nd.gov', 'cecogdill@nd.gov'] + + email = EmailMessage() + email['Subject'] = "Cohesity drive failure on {0}".format(cluster_name) + email['From'] = "No-Reply@nd.gov" + email['To'] = ", ".join(recipients) + email.set_content(body) + + with smtplib.SMTP('apprelay.nd.gov') as smtp: + smtp.send_message(email) + + print("Sent email") + +# Define variables +args = GetArgs() + +if args.debugMode: + debugMode = True +else: + debugMode = False + +# Check for arguments and act accoringly +if args.help: + PrintHelp() + exit(1) + +# Establish a connection to ServiceNow +if debugMode: + ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") +else: + ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +# Establish a connection to Cohesity +mycluster = cohesity.API(args.cluster) +authToken = mycluster.GetAuthToken() +mycluster.UpdateHeaders(authToken['accessToken']) + +# Set lookback period +if args.days: + d = args.days + if d > 0: + d = d * -1 +else: + d = -1 + +# Get yesterday's start time in unixEpoch: +prevWindow = mycluster.GetRelativeTimestamp(d, 0, 0, 0) +print(prevWindow) + +# Pull a list of protection runs from yesterday's backup window. +diskAlerts = mycluster.GetDiskAlerts(prevWindow) +print(diskAlerts) + +# Track disk id so we don't open multiple tickets for the same drive +disks = [] + +for alert in diskAlerts: + + alert_name = alert['alertDocument']['alertName'] + + # Valid alertNames: NewDiskFound, DriveRemoved, DiskOkToRemove, DiskNotHealthy, MarkDiskForRemoval + if alert_name == 'DiskNotHealthy' or alert_name == 'MarkDiskForRemoval': + for index in alert['propertyList']: + if index['key'] == 'disk_id': + disk_num = index['value'] + + # Ticket has already been opened for this disk + if disk_num in disks: + continue + else: + # Create the incident + incident = ticketSystem.submitTicket("svccohesityadm", "Cohesity Drive Failure: " + args.cluster , alert['alertDocument']['alertCause']) + incidentID = incident['result']['sys_id'] + + # Assign the incident to storage + ticketSystem.assignTicketToGroup(incidentID, 'NDIT-Cloud Platforms') + + message = "Cohesity Drive Failure" + body = "Incident: " + incident['result']['number'] + body = body + "\nFollow Procedure:" + body = body + "\n\thttps://northdakota.service-now.com/kb_view.do?sysparm_article=KB0014369" + + # Send the email to the list of recipients in the local SendEmail function + SendEmail(body, args.cluster) + + for index in alert['propertyList']: + if index['key'] == 'disk_id': + disks.append(index['value']) + + dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-dailyErrors.py', 'Units': 60}) diff --git a/_NDGOV_CS/ITD.Cohesity/findDuplicates.py b/_NDGOV_CS/ITD.Cohesity/findDuplicates.py new file mode 100644 index 0000000..f5cfb0e --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/findDuplicates.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import automationsAPI as dashboard + +# Global variables that will be used across all functions +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 sqlServerRegistration.py -c cluster.fqdn.tld") + print("\t -c FQDN of Cohesity cluster address") + print("\t -h Prints this help message") + +args = GetArgs() + +# Validate arguments & assign variables if necessary +if args.help: + PrintHelp() + exit(1) + +if not args.cluster: + PrintHelp() + exit(1) + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Provide a listing of all backedup vmWare objects. VMs should not be listed twice, requires manual review +itdvmvc2 = cluster.GetFilteredRequest("/public/protectionSources/protectedObjects", "?environment=kVMware&id=1") +for record in itdvmvc2: + if "protectionSource" in record: + if "protectionJobs" in record: + for jobs in record['protectionJobs']: + print(record['protectionSource']['name'] + ", " + jobs['name']) + +itdvmvc1 = cluster.GetFilteredRequest("/public/protectionSources/protectedObjects", "?environment=kVMware&id=3156") +for record in itdvmvc1: + if "protectionSource" in record: + if "protectionJobs" in record: + for jobs in record['protectionJobs']: + print(record['protectionSource']['name'] + ", " + jobs['name']) + +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-findDuplicates.py', 'Units': 60}) diff --git a/_NDGOV_CS/ITD.Cohesity/pauseOrResumeJob.py b/_NDGOV_CS/ITD.Cohesity/pauseOrResumeJob.py new file mode 100644 index 0000000..7f47c47 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/pauseOrResumeJob.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--type', '-t', type=str, action='store') + parser.add_argument('--job', '-j', type=str, action='store') + parser.add_argument('--pause', '-p', action='store_true') + parser.add_argument('--resume', '-r', action='store_true') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\n python3 pauseBackups.py -c cluster1.domain.tld -v vCenter.domain.tld [ -t kVMware, kPhysical, kSQL ] [ -p | -r ] [ -j protectionJobName ]") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v FQDN of vCenter Server, used in conjuntion with -t kVMware ") + print("\t -t Cohesity job type, kVMware, kPhysical, kSQL") + print("\t -j Cohesity job name") + print("\t -p Pause jobs that match the specified parameters") + print("\t -r Resume jobs that match the specified parameters") + print("\t -h Prints this help message") + +args = GetArgs() + +if args.help: + PrintHelp() + exit(1) + +if not args.cluster: + sys.exit("Error: Specify Cohesity cluster fqdn with -c parameter.") +elif args.type == "kVMware" and not args.vcenter: + sys.exit("Error: Specify vmware cluster address withe -v parameter when using type of kVMware.") +elif args.vcenter and not args.type: + args.type = "kVMware" +else: + cluster = cohesity.API(args.cluster) + authToken = cluster.GetAuthToken() + cluster.UpdateHeaders(authToken['accessToken']) + +if args.type=='kVMware' and args.vcenter: + vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") + + for source in vmSources: + if source['protectionSource']['name'] == args.vcenter: + vCenter = source + print (vCenter) + vCenterID = source['protectionSource']['id'] + break + + if args.job: + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + args.job) + else: + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") + print("Attempting to pause all jobs under " + args.vcenter) + + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + + if args.pause: + pausedJobs = [] + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + print("not vcenter") + continue + + elif "isDeleted" in job: + continue + + elif "isPaused" in job: + if job['isPaused']: + pausedJobs.append(job) + continue + + print("Pausing: " + job['name']) + resp = cluster.PauseJob(job['id']) + + print("The following jobs were previously paused before this operation.") + for pJob in pausedJobs: + print(pJob['name']) + + if args.resume: + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + continue + elif "isDeleted" in job: + continue + print("Resuming: " + job['name']) + resp = cluster.ResumeJob(job['id']) + +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-pauseOrResumeJob.py', 'Units': 60}) diff --git a/_NDGOV_CS/ITD.Cohesity/reNameJobs.py b/_NDGOV_CS/ITD.Cohesity/reNameJobs.py new file mode 100644 index 0000000..f50f27d --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/reNameJobs.py @@ -0,0 +1,130 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import sharePointAPI as sharePoint +import serviceNowAPI as snow +import automationsAPI as dashboard + + +# Global variables that will be used across all functions +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--verify', '-v', action='store_true') + parser.add_argument('--jobName', '-p', type=str, action='store') + parser.add_argument('--newJobName', '-n', type=str, action='store') + parser.add_argument('--unDelete', '-r', action='store_true') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 sqlServerRegistration.py -c cluster.fqdn.tld") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v force confirmation on change") + print("\t -p Protection job name, use in conjunction with -n") + print("\t -n New Protection job name, use in conjunction with -p") + print("\t -r Restore job from a deleted status, only used with single job operations") + print("\t -h Prints this help message") + +args = GetArgs() + +# Validate arguments & assign variables if necessary +if args.help: + PrintHelp() + exit(1) + +if not args.cluster: + PrintHelp() + exit(1) + +if args.jobName: + args.verify = True + if not args.newJobName: + PrintHelp() + exit(1) + +# ServiceNow object +ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +# Sharepoint Object +cmdb = sharePoint.API() + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +if args.jobName: + vmWareJobs=cluster.GetFilteredRequest("/public/protectionJobs","?names={0}".format(args.jobName)) +else: + vmWareJobs=cluster.GetFilteredRequest("/public/protectionJobs","?environments=kVMware&isActive=True") + +for job in vmWareJobs: + + preChangeNotes = json.dumps(job) + + if 'name' in job: + jobName = job['name'] + oldName = job['name'] + + + if args.newJobName: + print("\nUpdating job name for {0}".format(jobName)) + newName = args.newJobName + jobData = {"name": newName} + job.update(jobData) + + if args.unDelete: + print("\nRestoring job {0} from a deleted state.".format(jobName)) + jobData = {"isDeleted": False} + job.update(jobData) + + if '@PRD-itd' not in jobName and '@NPD-itd' not in jobName: + print("\nUpdating job name for {0}".format(jobName)) + x = jobName.split('@') + newName = x[0] + "@PRD-" + x[1] + jobData = {"name": newName} + job.update(jobData) + + print("Adding the exclude Test tag") + vcenterSource = cluster.GetFilteredRequest("/public/protectionSources", "?id=" + str(job['parentSourceId'])) + testTagId = cluster.GetVcenterTagId(vcenterSource, 'Test') + excludeData = {"excludeVmTagIds": [[testTagId]]} + job.update(excludeData) + + print("Updating to the new Policy Id") + policy = cluster.GetProtectionPolicyByName("ITD-Bronze-PRD") + policyData = {"policyId": policy[0]['id']} + job.update(policyData) + + if args.verify: + confirm = input("About to update protection job {0}. Are you sure? [yes|no] ".format(oldName)) + else: + confirm = "yes" + + if confirm.lower() == "yes": + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Computer Systems Storage", "svccohesityadm", "ndheck", "mlaverdure", "Computer Systems", "Backup/Restore", "Automated Change - Cohesity job update for {}".format(oldName), "Split production and non-production servers into multiple groups.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.addStandardChangeNotes(changeSysID, "Original job details\n\n{}".format(preChangeNotes)) + ticketSystem.reviewStandardChange(changeSysID) + + updateStats = cluster.UpdateVMProtectionJob(job) + + if updateStats.status_code != 200 and updateStats.status_code != 201: + postChangeNotes = "Job update failed\n\n" + updateStats.text + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Unsuccessful", "Change Failed") + else: + postChangeNotes = "Updated job name, added the exclude test tag, and updated the policy\n\n" + updateStats.text + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + + print("Chagne {} complete".format(changeID['result']['number']['value'])) diff --git a/_NDGOV_CS/ITD.Cohesity/registerServer.py b/_NDGOV_CS/ITD.Cohesity/registerServer.py new file mode 100644 index 0000000..2adc96f --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/registerServer.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +import sys +import argparse +import json +import time + +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import serviceNowAPI as serviceNow +import sharePointAPI as sharePoint +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--server', '-s', type=str, action='store') + parser.add_argument('--protectGroup', '-p', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + parser.add_argument('--debug', '-d', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 serverRegistration.py -s hostname.nd.gov -p MyApp@physical") + print("\t -s: Fully qualified domain name of the Server") + print("\t -p: Protection Group the server will be in") + print("\t -h Prints this help message") + +args = GetArgs() + +if not (args.server and args.protectGroup): + PrintHelp() + exit(1) + +# Proceed with registration +if (args.server and args.protectGroup): + try: + mdn = cohesity.API('itdmdndpc01.nd.gov') + mdnToken = mdn.GetAuthToken() + mdn.UpdateHeaders(mdnToken['accessToken']) + + newHost = args.server + protectionGroup = args.protectGroup + + isPhysicalRegistered = bool() + + # Get the physical server objects in Cohesity + physicalServers = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo", "?environments=kPhysical") + + for nodes in physicalServers['rootNodes']: + if nodes['rootNode']['name'] == newHost: + print(newHost + " is already registerd as a physical server.") + isPhysicalRegistered = bool("true") + physicalSourceId = nodes['rootNode']['id'] + break + + if not isPhysicalRegistered: + attempt = mdn.RegisterPhysical(newHost) + print("Registering " + newHost + " as a Physical Server ") + time.sleep(20) + try: + physicalSourceId = attempt['id'] + except: + print("\nCould not reach " + newHost + " on port 50051. Please verify the agent is running and that all firewall rules are accounted for.") + exit(1) + + # Get the list of protection groups & add the new one if necessary + protectionJobs = mdn.GetFilteredRequest("/public/protectionJobs", "?environments[0]=kPhysical") + uniqueJobs = {job['id'] : job for job in protectionJobs}.values() + jobExists = bool() + isProtected = bool() + jobSources = [] + + for job in uniqueJobs: + # Source ID cannot be in more then on protection group for SQL + if ('sourceIds' in job) and (physicalSourceId in job['sourceIds'] and ("DELETED" not in job['name']) ): + print(newHost + " is already in " + job['name'] + " and cannot be in multiple groups.") + isProtected = bool("true") + jobExists = bool("true") + break + + # The source ID was not found in any other SQL job, but a job name already exsits, so lets collect all sources in the job. + elif (job['name'] == protectionGroup) and ( physicalSourceId not in job['sourceIds']): + jobExists = bool("true") + break + + if jobExists == bool('true') and isProtected != bool('true'): + print("Adding host " + newHost + " to protection group " + protectionGroup) + + # By default we will protect all local drives + sourceParams = { + "sourceId": physicalSourceId, + "physicalSpecialParameters": { + "filePaths": [ + { + "backupFilePath":"$ALL_LOCAL_DRIVES", + "skipNestedVolumes":True + } + ], + "usesSkipNestedVolumesVec":True + } + } + + job["sourceIds"].append(physicalSourceId) + job["sourceSpecialParameters"].append(sourceParams) + resp = mdn.UpdateProtectionJob(job) + print(resp.content) + + if jobExists == bool(): + print("Creating protection job for " + protectionGroup + " and adding " + newHost) + ################ TO DO ############### + # Defaults from JSON dump of jobs objects + resp = mdn.CreatePhysicalProtectionJob(physicalSourceId, protectionGroup) + print(resp.content) + + except OSError as cohesityError: + print('Cohesity Error: ' + cohesityError) + +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Provisioning', 'Platform': 'Python-registerServer.py', 'Units': 30}) diff --git a/_NDGOV_CS/ITD.Cohesity/requirements.txt b/_NDGOV_CS/ITD.Cohesity/requirements.txt new file mode 100644 index 0000000..65d0530 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/requirements.txt @@ -0,0 +1,86 @@ +ansible==5.9.0 +ansible-core==2.12.10 +argcomplete==2.0.0 +bcrypt==3.2.2 +Beaker==1.10.0 +beautifulsoup4==4.11.0 +blivet==3.4.4 +blivet-gui==2.3.0 +Brlapi==0.8.4 +certifi==2023.11.17 +cffi==1.15.0 +chardet==4.0.0 +charset-normalizer==2.0.11 +click==8.0.4 +cryptography==36.0.0 +cupshelpers==1.0 +dasbus==1.6 +dbus-python==1.2.18 +distro==1.6.0 +fedora-third-party==0.10 +fros==1.1 +gpg==1.17.0 +humanize==3.13.1 +idna==3.3 +Jinja2==3.0.3 +langtable==0.0.61 +libcomps==0.1.18 +lxml==4.7.1 +Mako==1.1.4 +MarkupSafe==2.1.1 +nftables==0.1 +ntlm-auth==1.5.0 +olefile==0.46 +packaging==21.3 +paramiko==2.12.0 +Paste==3.5.0 +pathspec==0.10.1 +pexpect==4.8.0 +pid==2.2.3 +Pillow==9.1.0 +ply==3.11 +productmd==1.33 +ptyprocess==0.6.0 +pwquality==1.4.4 +pyasn1==0.4.8 +pycairo==1.21.0 +pycparser==2.20 +pycrypto==2.6.1 +pycups==2.0.1 +pycurl==7.45.1 +pyenchant==3.2.2 +PyGObject==3.42.1 +pykickstart==3.36 +PyNaCl==1.4.0 +pyOpenSSL==21.0.0 +pyparsing==2.4.7 +pyparted==3.12.0 +PySocks==1.7.1 +python-augeas==1.1.0 +python-dateutil==2.8.1 +python-meh==0.50 +pytz==2022.7 +pyudev==0.22.0 +pywinrm==0.4.1 +pyxdg==0.27 +PyYAML==6.0 +regex==2022.10.31 +requests==2.27.1 +requests-file==1.5.1 +requests-ftp==0.3.1 +requests-ntlm==1.1.0 +resolvelib==0.5.5 +rpm==4.17.1 +selinux==3.3 +sepolicy==3.3 +setools==4.4.0 +simpleaudio==1.0.4 +simpleline==1.9.0 +six==1.16.0 +sos==4.3 +soupsieve==2.3.1 +systemd-python==234 +Tempita==0.5.2 +urllib3==1.26.12 +xmltodict==0.12.0 +yamllint==1.28.0 diff --git a/_NDGOV_CS/ITD.Cohesity/sqlServerRegistration.py b/_NDGOV_CS/ITD.Cohesity/sqlServerRegistration.py new file mode 100644 index 0000000..c9e1433 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/sqlServerRegistration.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +""" +Allows for the registration of a SQL Server VM to Cohesity +""" +import sys +import argparse +import json +import time + +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import itdSnow as snow +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--server', '-s', type=str, action='store') + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--protectGroup', '-p', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + parser.add_argument('--debug', '-d', action='store_true') + parser.add_argument('--lookupGroup', '-l', action='store_true') + parser.add_argument('--audit', '-a', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 sqlServerRegistration.py -s hostname.nd.gov -p MyApp@SQL") + print("\t -a: Audit SQL objects and re-apply permissions") + print("\t -c: The FQDN of the cluster to register the client to") + print("\t -d: Run the registration in debug mode") + print("\t -l: Lookup appName in Sharepoint and propose Protection Group name") + print("\t -s: Fully qualified domain name of the Virtualized SQL Server") + print("\t -p: Protection Group the server will be in") + print("\t -h Prints this help message") + +args = GetArgs() +protectionGroup = '' +sqlHost='' + +# Establish a connection to ServiceNow +if args.debug: + ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") +else: + ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +if args.help: + PrintHelp() + exit(1) + +if not ((args.server and (args.lookupGroup or args.protectGroup)) or (args.audit)): + PrintHelp() + exit(1) + +# Get the AppName from the VM List in SharePoint +if args.server and args.lookupGroup: + sqlHost = args.server + cmdb_record = ticketSystem.getCMDBItemByFQDN(sqlHost) + print(json.dumps(cmdb_record,indent=4)) + appName = cmdb_record[0]['u_nd_application_svc']['name'] + +# shpt = sharePoint.API() +# vmRecord = shpt.get_Node(sqlHost) +# appName = shpt.get_AppName(vmRecord[0]['AppNameId']) + appName = appName + "@SQL" + + print("\nSuggested protection group name is: " + appName) + + menuControl = 0 + + while menuControl == 0: + contRegistration = input("Would you like to continue? [y/n]") + + if contRegistration == 'y' or contRegistration == 'Y': + menuControl = 1 + print("\nProceeding with registration.") + protectionGroup = appName + + elif contRegistration == 'n' or contRegistration == 'N': + menuControl = 1 + print("\nAuto lookup registration has been cancelled.") + print("\nPlease relaunch application with -s & -p parameters to specify a custom protection group.") + exit(1) + + else: + contRegistration = input("Would you like to continue? [y/n]") + +# Proceed with registration using either the SharePoint lookup value or the user specified value +if (((args.server or sqlHost) and (args.protectGroup or protectionGroup)) or args.audit): + try: + mdn = cohesity.API(args.cluster) + mdnToken = mdn.GetAuthToken() + mdn.UpdateHeaders(mdnToken['accessToken']) + + if (not sqlHost) and (not protectionGroup): + sqlHost = args.server + protectionGroup = args.protectGroup + + isSQLRegistered = bool() + isPhysicalRegistered = bool() + + # Get the VMs and SQL objects in Cohesity + #vms = mdn.GetRequest("/public/protectionSources/virtualMachines") + registeredSQL = mdn.GetFilteredRequest("/public/protectionSources/applicationServers", "?application=kSQL") + physicalServers = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo", "?environments=kPhysical") + + for nodes in physicalServers['rootNodes']: + if nodes['rootNode']['name'] == sqlHost: + print(sqlHost + " is already registerd as a physical server.") + isPhysicalRegistered = bool("true") + physicalSourceId = nodes['rootNode']['id'] + break + + # Check to see if the source is already registered as a SQL Server + for sqlServer in registeredSQL: + if sqlServer['applicationServer']['protectionSource']['name'] == sqlHost: + isSQLRegistered = bool("true") + print(sqlHost + " is already registerd as a SQL server.") + break + + if (sqlHost): + if not isPhysicalRegistered: + attempt = mdn.RegisterPhysical(sqlHost) + print("Registering " + sqlHost + " as a Physical Server ") + time.sleep(20) + try: + physicalSourceId = attempt['id'] + except: + print("\nCould not reach " + sqlHost + " on port 50051. Please verify the agent is running and that all firewall rules are accounted for.") + exit(1) + + if not isSQLRegistered: + print("Registering " + sqlHost + " as a SQL Server ") + attempt = mdn.RegisterSQL(physicalSourceId) + time.sleep(20) + + # Verify DBAs have permissions to all SQL objects, including newly registered objects + registeredSQL = mdn.GetFilteredRequest("/public/protectionSources/applicationServers", "?application=kSQL") + + # Filter out unique objects + uniqueSQLSources = {sql['applicationServer']['protectionSource']['id'] : sql for sql in registeredSQL}.values() + + # Array to hold protection source IDs + sqlProtectionSourceIds = [] + + for sqlServer in uniqueSQLSources: + sqlProtectionSourceIds.append(sqlServer['applicationServer']['protectionSource']['id']) + + # Send protection source IDs for DBA group + dbaGroup = mdn.GetFilteredRequest("/public/groups", "?name=ITD-COHESITY-DBA") + dbaSid = dbaGroup[0]['sid'] + print("Sending Request to Cohesity to update DBA permissions") + attempt = mdn.UpdatePermissions(sqlProtectionSourceIds, dbaSid) + + # Get the list of protection groups & add the new one if necessary + if (sqlHost): + sqlProtectionJobs = mdn.GetFilteredRequest("/public/protectionJobs", "?environments=kSQL") + uniqueJobs = {job['id'] : job for job in sqlProtectionJobs}.values() + jobExists = bool() + isProtected = bool() + isPaused=bool() + jobSources = [] + + for job in uniqueJobs: + # Source ID cannot be in more then on protection group for SQL + if ('sourceIds' in job) and (physicalSourceId in job['sourceIds'] and ("DELETED" not in job['name']) ): + print(sqlHost + " is already in " + job['name'] + " and cannot be in multiple groups.") + isProtected = bool("true") + jobExists = bool("true") + break + + # The source ID was not found in any other SQL job, but a job name already exsits, so lets collect all sources in the job. + elif (job['name'] == protectionGroup) and ( physicalSourceId not in job['sourceIds']): + jobExists = bool("true") + break + + if jobExists == bool('true') and isProtected != bool('true'): + isPaused=bool('true') + job["sourceIds"].append(physicalSourceId) + resp = mdn.UpdateProtectionJob(job) + print(resp.content) + + if jobExists == False: + print("Creating protection job for " + protectionGroup + " and adding " + sqlHost) + ################ TO DO ############### + # Defaults from JSON dump of jobs objects + if args.cluster == 'itdazdpc02.nd.gov': + resp = mdn.CreateAZSQLProtectionJob(physicalSourceId, protectionGroup) + else: + resp = mdn.CreateSQLProtectionJob(physicalSourceId, protectionGroup) + print(resp.content) + + except OSError as cohesityError: + print('Cohesity Error: ' + cohesityError) + +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Provisioning', 'Platform': 'Python-sqlServerRegistration.py', 'Units': 30}) diff --git a/_NDGOV_CS/ITD.Cohesity/template.py b/_NDGOV_CS/ITD.Cohesity/template.py new file mode 100644 index 0000000..819de43 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/template.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import sharePointAPI as sharePoint +import serviceNowAPI as snow +import automationsAPI as dashboard + + +# Global variables that will be used across all functions +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 sqlServerRegistration.py -c cluster.fqdn.tld") + print("\t -c FQDN of Cohesity cluster address") + print("\t -h Prints this help message") + +args = GetArgs() + +# Validate arguments & assign variables if necessary +if args.help: + PrintHelp() + exit(1) + +if not args.cluster: + PrintHelp() + exit(1) + +# ServiceNow object +ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") + +# Sharepoint Object +cmdb = sharePoint.API() + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Pull information from Cohestiy API +itdvmvc1 = cluster.GetFilteredRequest("/public/protectionSources/protectedObjects", "?environment=kVMware&id=3156") +for record in itdvmvc1: + if "protectionSource" in record: + if "protectionJobs" in record: + for jobs in record['protectionJobs']: + print(record['protectionSource']['name'] + ", " + jobs['name']) \ No newline at end of file diff --git a/_NDGOV_CS/ITD.Cohesity/unRegisterServer.py b/_NDGOV_CS/ITD.Cohesity/unRegisterServer.py new file mode 100644 index 0000000..600fb18 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/unRegisterServer.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +import sys +import argparse +import json +import time + +sys.path.insert(0, './classes/') +import cohesityAPI as cohesity +import serviceNowAPI as serviceNow +import sharePointAPI as sharePoint +import automationsAPI as dashboard + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--server', '-s', type=str, action='store') + parser.add_argument('--protectGroup', '-p', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + parser.add_argument('--debug', '-d', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 serverRegistration.py -s hostname.nd.gov -p MyApp@physical") + print("\t -s: Fully qualified domain name of the Server") + print("\t -p: Protection Group the server is in") + print("\t -h Prints this help message") + +args = GetArgs() + +if args.help: + PrintHelp() + exit() + +if args.debug: + debugMode = True +else: + debugMode = False + +cluster = cohesity.API('itdmdndpc01.nd.gov') +clusterToken = cluster.GetAuthToken() +cluster.UpdateHeaders(clusterToken['accessToken']) + +sourceId = cluster.GetProtectionSourceId(args.server) +pJob = cluster.GetProtectionJobByHost(args.server) + +if debugMode: + print("SourceId:\n==========") + print(sourceId) + + print("Job Info:\n==========") + print(pJob) + +# If the source is not tied to a protection job we will remove it anyway. +if pJob == -1: + print("No job was found, continuing to unregister server.") + removeSourceStat = cluster.RemoveProtectionSource(sourceId) + +else: + if sourceId in pJob['sourceIds']: + ids = pJob['sourceIds'] + ids.remove(sourceId) + pJob.update({'sourceIds': ids}) + + # Check to see if there are any specific source parameters, if so ensure we clean up those entries as well. + if 'sourceSpecialParameters' in pJob: + specialParams = pJob['sourceSpecialParameters'] + + for entry in specialParams: + if entry['sourceId'] == sourceId: + specialParams.remove(entry) + pJob.update({'sourceSpecialParameters': specialParams}) + + # Send the updated job information back to the cluster for updating + updateJobStat = cluster.UpdateProtectionJob(pJob) + + # Ensure the job was updated successfully + if updateJobStat.status_code != 200: + if debugMode: + print(updateJobStat) + print(updateJobStat.content) + sys.exit("Updating the protection job " + pJob['name'] + " failed.\n\nThe source " + args.server + " may be the only source for this job or have special parameters set in the protection job, manual intervention is required to clean up the protection group according to NDIT SLAs.") + + # Attempt to remove the source from the registered sources + removeSourceStat = cluster.RemoveProtectionSource(sourceId) + +# Ensure the source was removed successfully +if removeSourceStat.status_code == 403: + if debugMode: + print(removeSourceStat) + print(removeSourceStat.content) + sys.exit("Removing " + args.server + " from " + cluster.GetClusterName() + " has failed.") +print(args.server + " has been unregistered from " + cluster.GetClusterName()) +dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'DeProvisioning', 'Platform': 'Python-unRegisterServer.py', 'Units': 30}) diff --git a/_NDGOV_CS/ITD.Cohesity/updateAzPolicy.py b/_NDGOV_CS/ITD.Cohesity/updateAzPolicy.py new file mode 100644 index 0000000..f1fd86b --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/updateAzPolicy.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import sharePointAPI as sharePoint +import serviceNowAPI as snow +import automationsAPI as dashboard + + +# Global variables that will be used across all functions +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--verify', '-v', action='store_true') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 sqlServerRegistration.py -c cluster.fqdn.tld") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v force confirmation on change") + print("\t -h Prints this help message") + +args = GetArgs() + +# Validate arguments & assign variables if necessary +if args.help: + PrintHelp() + exit(1) + +if not args.cluster: + PrintHelp() + exit(1) + +# ServiceNow object +ticketSystem = snow.SnowAPI("northdakota.service-now.com") + +# Sharepoint Object +cmdb = sharePoint.API() + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +vmWareJobs=cluster.GetFilteredRequest("/public/protectionJobs","?environments=kAzureNative&isActive=True") + +for job in vmWareJobs: + preChangeNotes = json.dumps(job) + if 'name' in job: + jobName = job['name'] + + if '@cares01' in jobName: + continue + print("\nUpdating policy for {0}".format(jobName)) + policyData = {"policyId": "7780085755317378:1694019083558:285" + + if '@infra01' in jobName: + continue + print("\nUpdating policy for {0}".format(jobName)) + policyData = {"policyId": "7780085755317378:1694019083558:286"} + job.update(policyData) + + elif '@npd01' in jobName: + continue + print("\nUpdating policy for {0}".format(jobName)) + policyData = {"policyId": "7780085755317378:1694019083558:287"} + job.update(policyData) + + elif '@prd01' in jobName: + print("\nUpdating policy for {0}".format(jobName)) + policyData = {"policyId": "7780085755317378:1694019083558:288"} + job.update(policyData) + + else: + continue + + if args.verify: + confirm = input("About to update protection job {0}. Are you sure? [yes|no] ".format(jobName)) + else: + confirm = "yes" + + if confirm.lower() == "yes": + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Computer Systems", "Backup/Restore", "Automated Change - Cohesity job update for {}".format(jobName), "Update protection policy to enable replication.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.addStandardChangeNotes(changeSysID, "Original job details\n\n{}".format(preChangeNotes)) + ticketSystem.reviewStandardChange(changeSysID) + + updateStats = cluster.UpdateVMProtectionJob(job) + + if updateStats.status_code != 200 and updateStats.status_code != 201: + postChangeNotes = "Job update failed\n\n" + updateStats.text + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Unsuccessful", "Change Failed") + else: + postChangeNotes = "Updated the policy\n\n" + updateStats.text + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + + print("Change {} complete".format(changeID['result']['number']['value'])) diff --git a/_NDGOV_CS/ITD.Cohesity/updateAzProtectionJobs.py b/_NDGOV_CS/ITD.Cohesity/updateAzProtectionJobs.py new file mode 100644 index 0000000..363dc0e --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/updateAzProtectionJobs.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import automationsAPI as dashboard +import nditServiceNow as snow +import random + +# Global variables that will be used across all functions + +global tagName +tagName = None + +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--tag', '-t', type=str, action='store') + parser.add_argument('--group', '-g', type=str, action='store') + parser.add_argument('--action', '-a', type=str, action='store') + parser.add_argument('--list', '-l', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 updateProtectionGroupTags.py -c hostname.nd.gov") + print("\t -c FQDN of Cohesity cluster address") + print("\t -g Protection group name") + print("\t -a Action to perform 'add' or 'remove'") + print("\t -l List that needs to be updated, the 'include' or 'exclude'") + print("\t -h Prints this help message") + +args = GetArgs() + +if args.help: + PrintHelp() + exit(1) + +# Validate arguments & assign variables if necessary +if not args.cluster: + sys.exit("Error: Specify a Cohesity cluster fqdn with -c parameter.") + + +vmObjects = [] +protectedObjects = [] +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) +ticketSystem = snow.SnowAPI("northdakota.service-now.com") +nodes = cluster.GetAZsources() + +subscription = input("Which subscription do you want to update? [prd01,npd01,cares01,infra01] ") +if subscription == 'npd01': + subId = 1 + plcyId = "7780085755317378:1694019083558:287" + +elif subscription == 'infra01': + subId = 28 + plcyId = "7780085755317378:1694019083558:286" + +elif subscription == 'prd01': + subId = 37 + plcyId = "7780085755317378:1694019083558:288" + +elif subscription == 'cares01': + subId = 4 + plcyId = "7780085755317378:1694019083558:285" + +sId = subId + +nodes = cluster.GetAZsources() + +for node in nodes: + + if node['protectionSource']['id'] == subscription: + hypervisorId = node['protectionSource']['id'] + cluster.RefreshSource(node['protectionSource']['id']) + + myObjects = cluster.GetAZObjects(hypervisorId) + myProtectedObjects = cluster.GetProtectedAZobjects(hypervisorId) + + for val in myObjects: + vmObjects.append(val) + + for val in myProtectedObjects: + protectedObjects.append(val) + +sourceJobs = cluster.GetAZNativeJobs() + +for job in sourceJobs: + + if job['parentSourceId'] != subId: + continue + + print("\nPreparing to update {0}".format(job['name'])) + tagName = job['name'].split('@')[0] + subName = job['name'].split('@')[1] + + #confirm = input("The tag to protect for this job is {0}. Is that correct? [y/n]".format(tagName)) + confirm = 'y' + + while confirm != 'y' and confirm != 'n': + confirm = input("Please enter 'y' or 'n': ") + + if confirm == 'n': + tagName = input("Enter the correct tag: ") + elif confirm == 'y': + + subSource = cluster.GetFilteredRequest("/public/protectionSources", "?id=" + str(sId)) + tagId = cluster.GetAzureTagId(subSource, tagName) + + changeID = ticketSystem.CreateStandardChange("NDIT-SPS-Cohesity Data Protection", "NDIT-Cloud Platforms", "svccohesityadm", "ndheck", "mlaverdure", "Systems Platforms - Systems", "Backup/Restore", "Automated Change - Update protection job {0}".format(job['name']), "Adjust start time.") + changeSysID = changeID['result']['sys_id']['value'] + ticketSystem.scheduleStandardChange(changeSysID) + ticketSystem.implementStandardChange(changeSysID) + ticketSystem.reviewStandardChange(changeSysID) + + rmin = [0,15,30,45] + smin = random.choice(rmin) + + rhr = [17,18,19,20,21,22,23,0,1,2,3,4,5] + shr = random.choice(rhr) + + if(tagId is not None): + data = { + "name": job['name'], + "description": "", + "policyId": plcyId, + "storageDomainId": 36, + "startTime": { + "hour": shr, + "minute": smin, + "timezone": "America/Chicago" + }, + "priority": "kMedium", + "sla": [ + { + "backupRunType": "kIncremental", + "slaMinutes": 480 + }, + { + "backupRunType": "kFull", + "slaMinutes": 480 + } + ], + "isPaused": False, + "abortInBlackoutPeriod": False, + "environment": "kAzure", + "azureParams": { + "protectionType": "kNative", + "nativeProtectionTypeParams":{ + "objects": [], + "vmTagIds": [ + [ + tagId + ] + ], + #"excludeVmTagIds": False, + "indexingPolicy":{ + "enableIndexing": True, + "includePaths": [ + "/" + ], + "excludePaths": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/splunk", + ] + }, + }, + }, + "abortInBlackoutPeriod": False + } + + job.update(data) + resp = cluster.UpdateAZprotectionJob(job) + postChangeNotes = resp.text + ticketSystem.addStandardChangeNotes(changeSysID, postChangeNotes) + ticketSystem.closeStandardChange(changeSysID, "Successful", "Change Complete") + + dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-updateProtectionGroupTags.py', 'Units': 10}) diff --git a/_NDGOV_CS/ITD.Cohesity/updateIndexingPolicy.py b/_NDGOV_CS/ITD.Cohesity/updateIndexingPolicy.py new file mode 100644 index 0000000..a235bc0 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/updateIndexingPolicy.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--job', '-j', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("Set OS environment variables ITD_SHAREPOINT_PASS and ITD_SHAREPOINT_USER") + print("\nExample:") + print(r"$ export COHESITY_USER=\"NDGOV\jDoe\"") + print("$ export COHESITY_PASS=\"1Lik3Jane\"") + print("\n python3 -c cluster1.domain.tld [ -v vCenter.domain.tld ] [ -j protectionJobName ]") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v FQDN of vCenter Server, used in conjuntion with -t kVMware ") + print("\t -j Cohesity job name") + print("\t -h Prints this help message") + +args = GetArgs() + +if args.help: + PrintHelp() + +if not args.cluster: + sys.exit("Error: Specify Cohesity cluster fqdn with -c parameter.") +else: + cluster = cohesity.API(args.cluster) + authToken = cluster.GetAuthToken() + cluster.UpdateHeaders(authToken['accessToken']) + +if args.vcenter: + vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") + + for source in vmSources: + if source['protectionSource']['name'] == args.vcenter: + vCenter = source + vCenterID = source['protectionSource']['id'] + break + + if args.job: + # Get the details of a single job + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + args.job) + else: + # Get the details of all jobs under a vCenter + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") + + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + +# Do stuff with the JSON data +# Example: + if args.pause: + pausedJobs = [] + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + print("not vcenter") + continue + + elif "isDeleted" in job: + continue + + elif "isPaused" in job: + if job['isPaused']: + pausedJobs.append(job) + continue + + print("Pausing: " + job['name']) + resp = cluster.PauseJob(job['id']) + + print("The following jobs were previously paused before this operation.") + for pJob in pausedJobs: + print(pJob['name']) + + if args.resume: + for job in uniqueJobs: + if job['parentSourceId'] != vCenterID: + continue + + elif "isDeleted" in job: + continue + + print("Resuming: " + job['name']) + resp = cluster.ResumeJob(job['id']) + +elif args.job: + job = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + args.job) + + job[0].update({"indexingPolicy":{ + "disableIndexing": False, + "allowPrefixes": [ + "/" + ], + "denyPrefixes": [ + "/$Recycle.Bin", + "/Windows", + "/ProgramData", + "/System Volume Information", + "/Users/*/AppData", + "/Recovery", + "/usr", + "/sys", + "/proc", + "/lib", + "/grub", + "/grub2", + "/opt/splunk", + "/splunk", + ] + }}) + + resp = cluster.UpdateVMProtectionJob(job[0]) diff --git a/_NDGOV_CS/ITD.Cohesity/updateProtectionGroupTags.py b/_NDGOV_CS/ITD.Cohesity/updateProtectionGroupTags.py new file mode 100644 index 0000000..68c0ef4 --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/updateProtectionGroupTags.py @@ -0,0 +1,268 @@ +#!/usr/bin/python +import sys,argparse,json,time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity +import automationsAPI as dashboard + +# Global variables that will be used across all functions +global tagid +tagid = None + +global tagName +tagName = None + +# Begin Functions + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--cluster', '-c', type=str, action='store') + parser.add_argument('--vcenter', '-v', type=str, action='store') + parser.add_argument('--tag', '-t', type=str, action='store') + parser.add_argument('--group', '-g', type=str, action='store') + parser.add_argument('--action', '-a', type=str, action='store') + parser.add_argument('--list', '-l', type=str, action='store') + parser.add_argument('--help', '-h', action='store_true') + return (parser.parse_args()) + +def PrintHelp(): + print("\nBasic Usage:") + print("\npython3 updateProtectionGroupTags.py -c hostname.nd.gov -p MyApp@SQL") + print("\t -c FQDN of Cohesity cluster address") + print("\t -v FQDN of vCenter Server") + print("\t -t vmWare Tag Name") + print("\t -g Protection group name") + print("\t -a Action to perform 'add' or 'remove'") + print("\t -l List that needs to be updated, the 'include' or 'exclude'") + print("\t -h Prints this help message") + +def GetTagID(sources): + globalList = globals() + + for source in sources: + if globalList['tagid'] is None: + GetNode(sources) + +def GetNode(record): + globalList = globals() + + # A non 'node' element was found, check each child key to see if one contains 'kTag' + if "protectionSource" in record: + if "vmWareProtectionSource" in record['protectionSource']: + if record['protectionSource']['vmWareProtectionSource']['type'] == "kTag": + + # Tag elements have been found, look for the correct tag and assign the id to the global variable + if record['protectionSource']['vmWareProtectionSource']['name'] == globalList['tagName']: + + # Tag was found based on the name + globalList['tagid'] = record['protectionSource']['id'] + print('Tag was found with ID: ' + str(record['protectionSource']['id'])) + + # Recurse through all 'nodes' elements looking for kTag + if "nodes" in record: + for node in record['nodes']: + + # The tag hasn't been found, search the next record + if globalList['tagid'] is None: + GetNode(node) + + # The tag was found and the global id value was set, stop iterating. + else: + break + +def UpdateProtectionGroupExcludes(group, action): + globalList = globals() + isExcluded = False + tagArray = [] + + if "excludeVmTagIds" in group: + for index in group['excludeVmTagIds']: + for tag in index: + tagArray.append(tag) + if tag == globalList['tagid']: + isExcluded = True + + # Add the tag to the exclusion + if action == 'add': + if isExcluded == True: + print(globalList['tagName'] + " tag is already excluded for " + group['name']) + else: + print("Adding exclusion tag '" + globalList['tagName'] + "' to group " + group['name']) + tagArray.append(globalList['tagid']) + + # Remove the tag from the exclusion + elif action == 'remove': + if isExcluded == True: + print("Removing exclusion tag '" + globalList['tagName'] + "' from group " + group['name']) + tagArray.remove(globalList['tagid']) + else: + print(globalList['tagName'] + " tag is not excluded for " + group['name']) + + + return(tagArray) + +def UpdateProtectionGroupIncludes(group, action): + globalList = globals() + isIncluded = False + + tagArray = [] + + if "vmTagIds" in group: + for index in group['vmTagIds']: + for tag in index: + tagArray.append(tag) + if tag == globalList['tagid']: + isIncluded = True + + # Add the tag to the inclusion + if action == 'add': + if isIncluded == True: + print(globalList['tagName'] + " tag is already included for " + group['name']) + else: + print("Adding inclusion tag '" + globalList['tagName'] + "' to group " + group['name']) + tagArray.append(globalList['tagid']) + + # Remove the tag from the inclusion + elif action == 'remove': + if isIncluded == True: + print("Removing inclusion tag '" + globalList['tagName'] + "' from group " + group['name']) + tagArray.remove(globalList['tagid']) + else: + print(globalList['tagName'] + " tag is not included for " + group['name']) + + return(tagArray) + + +# Begin Main +globalList = globals() + +sourceFound = False +vCenter = None +vCenterID = None +tagIds = [] + +args = GetArgs() + +if args.help: + PrintHelp() + exit(1) + +# Validate arguments & assign variables if necessary +if not args.cluster: + sys.exit("Error: Specify a Cohesity cluster fqdn with -c parameter.") +else: + globalList['tagName'] = args.tag + +if not args.vcenter: + sys.exit("Error: Specify a vCenter with -v parameter") + +if not args.tag: + sys.exit("Error: Specify a tag with the -t parameter.") + +if not args.action: + sys.exit("Error: Specify an action [add|remove] with -a parameter.") +elif args.action != 'add' and args.action != 'remove': + sys.exit("Error: Use only 'add' or 'remove' with -a parameter.") + +if not args.list: + sys.exit("Error: Specify a list [include|exclude] with -l parameter.") +elif args.list != 'exclude' and args.list != 'include': + sys.exit("Error: Use only 'include' or 'exclude' with -l parameter.") + +# Connect to the Cohesity cluster +cluster = cohesity.API(args.cluster) +authToken = cluster.GetAuthToken() +cluster.UpdateHeaders(authToken['accessToken']) + +# Locate the correct vCenter and capture the id, this will be useful to validate child objects +vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") +for source in vmSources: + if source['protectionSource']['name'] == args.vcenter: + sourceFound = True + vCenter = source + vCenterID = source['protectionSource']['id'] + break + +# The vCenter we are looking for was not in the list of kVMware environments, stop processing. +if sourceFound == False: + sys.exit("Error: " + args.vcenter + " is not registered to " + args.cluster) + +# Look up the tag id based on the tagName and set a global variable when found +# IMPROVEMENT TO GET AWAY FROM GLOBAL VAR +GetTagID(vCenter) + +if globalList['tagid'] is None: + sys.exit("Error: The tag '" + args.tag + "' does not exist in " + vCenter['protectionSource']['name']) + +if args.group: + # Replace '@' symbol with '%40' for URL encoding in the REST API + protectionGroup = args.group.replace("@","%40") + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + protectionGroup) + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + + for job in uniqueJobs: + + if job['parentSourceId'] != vCenterID: + sys.exit(job['name'] + " does not belong to source " + vCenter['protectionSource']['name']) + else: + if 'isDeleted' in job: + continue + + if (args.list == 'exclude'): + excludeTagIds = UpdateProtectionGroupExcludes(job, args.action) + if "excludeVmTagIds" in job: + job['excludeVmTagIds'][0] = excludeTagIds + else: + job.update({"excludeVmTagIds": [ excludeTagIds ]}) + else: + includeTagIds = UpdateProtectionGroupIncludes(job, args.action) + if "vmTagIds" in job: + job['vmTagIds'][0] = includeTagIds + else: + job.update({"includeVmTagIds": [ includeTagIds ]}) + + # Take acion on group(s) + resp = cluster.UpdateVMProtectionJob(job) + print(resp.content) + +else: + vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") + uniqueJobs = {job['id'] : job for job in vmJobs}.values() + + for job in uniqueJobs: + if "isPaused" in job: + if job['isPaused'] == True: + continue + # If the job is marked for deletion, skip + if 'isDeleted' in job: + if job['isDeleted'] == True: + continue + + # If the job does not belong to this vCetner, skip + if job['parentSourceId'] != vCenterID: + continue + else: + if (args.list == 'exclude'): + excludeTagIds = UpdateProtectionGroupExcludes(job, args.action) + + if "excludeVmTagIds" in job: + job['excludeVmTagIds'][0] = excludeTagIds + else: + job.update({"excludeVmTagIds": [ excludeTagIds ]}) + + else: + includeTagIds = UpdateProtectionGroupIncludes(job, args.action) + + if "vmTagIds" in job: + job['vmTagIds'][0] = includeTagIds + else: + job.update({"includeVmTagIds": [ includeTagIds ]}) + + # Take action on group(s) + resp = cluster.UpdateVMProtectionJob(job) + + +if args.group: + dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-updateProtectionGroupTags.py', 'Units': 10}) +else: + dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Maintenance', 'Platform': 'Python-updateProtectionGroupTags.py', 'Units': 240}) diff --git a/_NDGOV_CS/ITD.Cohesity/vars/exemptions.yml b/_NDGOV_CS/ITD.Cohesity/vars/exemptions.yml new file mode 100644 index 0000000..655faec --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/vars/exemptions.yml @@ -0,0 +1,171 @@ +# All entries must be in lower case, the scripts will normalize all hostnames to lowercase to match. +--- +azureNPD01: + id: 1 + jobs: + - "none" + vms: + # INC0410358 + - "^itd\\S+pamac[0-9]+" + - "^itd\\S+pamac\\S+[0-9]+" + - "^vm-itd\\S+pamac[0-9]+" + - "^vm-itd\\S+pamac\\S+[0-9]+" + # INC0410366 + - "sntest" + # INC0572225 + - "itdsosblscmtwt1" + templates: + - "[a-z]*" +azurePRD01: + id: 37 + jobs: + - "none" + vms: + # INC0410358 + - "^itd\\S+pamac[0-9]+" + - "^itd\\S+pamac\\S+[0-9]+" + - "^vm-itd\\S+pamac[0-9]+" + - "^vm-itd\\S+pamac\\S+[0-9]+" + # INC0410366 + - "sntest" + templates: + - "[a-z]*" +azureCARES01: + id: 4 + jobs: + - "none" + vms: + - "itdmltesting" + # INC0410358 + - "^itd\\S+pamac[0-9]+" + - "^itd\\S+pamac\\S+[0-9]+" + - "^vm-itd\\S+pamac[0-9]+" + - "^vm-itd\\S+pamac\\S+[0-9]+" + # INC0410366 + - "sntest" + templates: + - "[a-z]*" +azureINFRA01: + id: 28 + jobs: + # INC0410358 + - "Infra-Networking-PA@infra01" + # INC0199104 + - "Infra-Azure-Networking-Infoblox@infra01" + vms: + # INC0410358 + - "^itd\\S+pamac[0-9]+" + - "^itd\\S+pamac\\S+[0-9]+" + - "itdinfrapanoramalab-prd-400" + - "^vm-itd\\S+pamac[0-9]+" + - "^vm-itd\\S+pamac\\S+[0-9]+" + - "vm-itdinf01exmac01-prd-001" + - "vm-itdinf01exmac02-prd-001" + - "itdinf01exmac01-prd-001" + - "itdinf01exmac02-prd-001" + - "vm-itdinfra01sharedbackuppamac001-prd-001" + - "vm-itdinfra01sharedbackuppamac002-prd-002" + - "itdinfra01sharedbackuppamac001-prd-001" + - "itdinfra01sharedbackuppamac002-prd-002" + # INC0199104 + - "^vm-ns[0-9]+-prd-[0-9]+" + - "ns13.ns.nd.gov" + - "ns14.ns.nd.gov" + # INC0422813, INC0422812 + - "(^vm?|^itd?)\\S+infra\\S+srx\\S+" + # INC0422811 + - "itdnettestingsrx" + # Documented exception, these are the cohesity servers themselves + - "sa[0-9]*" + # INC0410366 + - "sntest" + templates: + - "[a-z]*" +azurePAAS01: + id: 12226 + jobs: + - "Infra-Networking-PA@NDIT-PaaS" + vms: + - "^vm-itd\\S+pamac[0-9]+" + - "^vm-itd\\S+pamac\\S+us[0-9]+" + templates: + - "[a-z]*" +itdvmvc2: + id: 1 + jobs: + - "ITD-POC-zmeier@itdvmvc2" + vms: + # INC0410366 + - "clone" + - "delete" + - "broken" + - "itdzmtest" + - "sntest" + # RITM0413140 + - "^itdnessus[0-9]+" + templates: + - "[a-z]*" +itdvmvc1: + id: 3156 + jobs: + # INC0428498 + - "itd-poc-zmeier@itdvmvc1" + - "ITD-POC-zmeier@itdvmvc1" + # INC0468249 + - "NDPERS-Applications@physical" + sql: + # DBA's are using RedGate on this server + - "itdsql16p3.nd.gov" + vms: + # RITM0413140 + - "^itdnessus[0-9]+" + # INC0199104 + - "infoblox-egmv1.ns.nd.gov" + - "infoblox-gmv1.ns.nd.gov" + - "vm-ns4.ndnic.com-prd-400" + # INC0152611 + - "itdavayarec.nd.gov" + - "itdbiscmsvra.nd.gov" + - "itdbiscmsvrb.nd.gov" + - "itdwfoaes4.nd.gov" + # INC0410383 + - "itdcaldera1" + - "itdcuckoo1" + - "itdcape1" + - "itdcape2" + - "itdremnux" + - "itdflarevm" + # INC0488924 + - "itdremworkstation.nd.gov" + - "itdremworkstation" + # INC0410366 + - "sntest" + - "clone" + - "delete" + - "broken" + - "itdzmtest" + # INC0488902 / 20250310 (vantis) + - "admin_vm" + - "controller0" + - "controller1" + - "controller2" + - "worker0" + - "worker1" + - "worker2" + - "worker3" + - "security" + - "bastion" + - "admin" + # INC0848221 + - "Windows Server 2025 Standard 24H2.6" + templates: + - "[a-z]*" +itdvmvct1: + id: 8557 + jobs: + - "[a-z]*" + vms: + - "[a-z]*" + - "sntest" + templates: + - "[a-z]*" diff --git a/_NDGOV_CS/ITD.Cohesity/verified/validate_replication.py b/_NDGOV_CS/ITD.Cohesity/verified/validate_replication.py new file mode 100644 index 0000000..cf804eb --- /dev/null +++ b/_NDGOV_CS/ITD.Cohesity/verified/validate_replication.py @@ -0,0 +1,126 @@ +#!/usr/bin/python +import sys,argparse,json,time +import time +sys.path.insert(0, './classes/') + +import cohesityAPI as cohesity + +def GetArgs(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--source', '-s', type=str, action='store') + parser.add_argument('--replica', '-r', type=str, action='store') + parser.add_argument('--delete', '-del', type=str, action='store') + return (parser.parse_args()) + +args = GetArgs() + +# Connect to the Cohesity cluster +source_cluster = cohesity.API(args.source) +source_token = source_cluster.GetAuthToken() +source_cluster.UpdateHeaders(source_token['accessToken']) +source_jobs = source_cluster.GetRequest("/public/protectionJobs") + +# Connect to the Replica cluster +replica_cluster = cohesity.API(args.replica) +replica_token = replica_cluster.GetAuthToken() +replica_cluster.UpdateHeaders(replica_token['accessToken']) +replica_jobs = replica_cluster.GetRequest("/public/protectionJobs") + +deleted_on_source=[] +deleted_on_remote=[] +source_only=[] +remote_only=[] + +legal_holds_on_deleted_jobs=[] + +for s_job in source_jobs: + if 'isDeleted' in s_job: + if s_job['isDeleted'] == True: + deleted_on_source.append(s_job) + + # Verify there aren't any orphaned snapshots due to legal holds + p = s_job['policyId'].split(":") + policy = str(p[0])+":"+str(p[1])+":"+str(s_job['id']) + run_data = source_cluster.GetRequestV2("/data-protect/protection-groups/"+policy+"/runs?numRuns=1000") + runs = run_data['runs'] + + for run in runs: + if run['onLegalHold']: + url = "https://{0}/protection/group/run/backup/{1}/{2}".format(args.source,run['protectionGroupId'],run['id']) + legal_holds_on_deleted_jobs.append(url) + + continue + + is_on_both = False + issource_only = False + isremote_only = False + + for r_job in replica_jobs: + if s_job['name'] == r_job['name']: + is_on_both = True + + if is_on_both: + continue + + else: + source_only.append(s_job) + +for r_job in replica_jobs: + is_on_both = False + issource_only = False + isremote_only = False + + if 'isDeleted' in r_job: + if r_job['isDeleted'] == True: + deleted_on_replica.append(r_job) + + # Verify there aren't any orphaned snapshots due to legal holds + p = r_job['policyId'].split(":") + policy = str(p[0])+":"+str(p[1])+":"+str(r_job['id']) + run_data = replica_cluster.GetRequestV2("/data-protect/protection-groups/"+policy+"/runs?numRuns=1000") + runs = run_data['runs'] + + for run in runs: + if run['onLegalHold']: + url = "https://{0}/protection/group/run/backup/{1}/{2}".format(args.replica,run['protectionGroupId'],run['id']) + legal_holds_on_deleted_jobs.append(url) + + continue + + for s_job in source_jobs: + if s_job['name'] == r_job['name']: + is_on_both = True + + if is_on_both: + continue + + else: + remote_only.append(r_job) + +print("\nSource Only:") +for src_val in source_only: + #resp = source_cluster.DeleteJob("/public/protectionJobs/"+str(value['id'])) + #print(resp.content) + print(src_val['name']) + +print("\nRemote Only:") +for repl_val in remote_only: + print(repl_val['name']) + + if (args.delete): + print("Deleting " + repl_val['name'] + " on replica") + resp = replica_cluster.DeleteJob("/public/protectionJobs/"+str(value['id'])) + print(resp.content) + + +print("\nDeleted in Source:") +for del_val in deleted_on_source: + print(del_val['name']) + +print("\nDeleted on Replica:") +for del_val in deleted_on_source: + print(del_val['name']) + +print("\nDeleted Jobs with legal holds on snapshots:") +for lh in legal_holds_on_deleted_jobs: + print(json.dumps(lh,indent=2)) diff --git a/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psd1 b/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psd1 new file mode 100644 index 0000000..45fe0b5 --- /dev/null +++ b/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psd1 @@ -0,0 +1,139 @@ +# +# Module manifest for module 'PSGet_ITDAzureRM' +# +# Generated by: zmeier +# +# Generated on: 2/18/2019 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'ITDAzureRM.psm1' + +# Version number of this module. +ModuleVersion = '0.4.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'dec17c9a-f0ec-439f-ac81-bc24a4815115' + +# Author of this module +Author = 'zmeier','cdfelchle' + +# Company or vendor of this module +CompanyName = 'Unknown' + +# Copyright statement for this module +Copyright = '(c) 2019 zmeier. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Functions for Azure Resource Manager administrative tasks' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows 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 = 'Set-ITDAzureRMResourceGroupAssignment', 'Get-ITDAzureRMIPs', + 'Set-ITDAzureRMResourceGroupTags', + 'Set-ITDAzureRMResourceGroupTagsRefresh', + 'New-ITDAzureRMPolicyDefinition', + 'Find-ITDAzureRMUntaggedResources', 'New-ITDAzureRMVM', + 'Remove-ITDAzureRMResourceGroupTags', 'Add-ITDAzureRMNewDataDisk', + 'New-ITDAzureVM', 'New-ITDAzureRMResourceGroup', 'Find-ITDAzureRMVM', + 'Set-ITDAzureRmVMBackup' + +# 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 = '' + +} + diff --git a/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psm1 b/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psm1 new file mode 100644 index 0000000..0592eb7 --- /dev/null +++ b/_NDGOV_CS/ITDAzureRM/ITDAzureRM.psm1 @@ -0,0 +1,1437 @@ +<# +.Synopsis + Sets Common Permissions on a Resource Group depending on Ownershiptest +.DESCRIPTION + Long description +.EXAMPLE + Set-ITDAzureRMResourceGroupAssignment -Ownership VM -ResourceGroup rg-itd-resourcegroup-tst +.EXAMPLE + Set-ITDAzureRMResourceGroupAssignment -Ownership Network -ResourceGroup rg-itd-netresourcegroup-tst +#> +function Set-ITDAzureRMResourceGroupAssignment +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Param1 help description + [Parameter(Mandatory=$true, Position=0)] + [String] + $Ownership, + + # Param2 help description + [Parameter(Mandatory=$true,Position=1)] + [string] + $ResourceGroup + ) + + Begin + { + $Tenant = (Get-AzureRMContext).Environment.Name + } + Process + { + If ($Ownership -eq "VM"){ + If($Tenant -eq "AzureUSGovernment") + { + $ADGroupOperator = Get-AzureRMADGroup -SearchString "ITD-MAG-VM-Operator" + $ADGroupContributor = Get-AzureRMADGroup -SearchString "ITD-MAG-VM-Contributor" + } + Elseif($Tenant -eq "AzureCloud") + { + $ADGroupOperator = Get-AzureRMADGroup -SearchString "ITD-MAC-VM-Operator" + $ADGroupContributor = Get-AzureRMADGroup -SearchString "ITD-MAC-VM-Contributor" + } + New-AzureRMRoleAssignment -ObjectID $ADGroupOperator.Id.ToString() -RoleDefinitionName "ITD-VM-Operator" -ResourceGroup $ResourceGroup + New-AzureRMRoleAssignment -ObjectID $ADGroupContributor.Id.ToString() -RoleDefinitionName "ITD-VM-Contributor" -ResourceGroup $ResourceGroup + } + + If ($Ownership -eq "Network"){ + If($Tenant -eq "AzureUSGovernment") + { + $ADGroupOperator = Get-AzureRMADGroup -SearchString "ITD-MAG-Network-Operator" + $ADGroupContributor = Get-AzureRMADGroup -SearchString "ITD-MAG-Network-Contributor" + } + Elseif($Tenant -eq "AzureCloud") + { + $ADGroupOperator = Get-AzureRMADGroup -SearchString "ITD-MAC-Network-Operator" + $ADGroupContributor = Get-AzureRMADGroup -SearchString "ITD-MAC-Network-Contributor" + } + New-AzureRMRoleAssignment -ObjectID $ADGroupOperator.Id.ToString() -RoleDefinitionName "ITD-VM-Operator" -ResourceGroup $ResourceGroup + New-AzureRMRoleAssignment -ObjectID $ADGroupContributor.Id.ToString() -RoleDefinitionName "ITD-VM-Contributor" -ResourceGroup $ResourceGroup + } + } + End + { + } +} + + +<# +.Synopsis + Gets all Azure IP's Across MAC and MAG and outputs to text files +.DESCRIPTION + Long description +.EXAMPLE + Get-ITDAzureRMIPs -OutputPath "C:\temp" +.EXAMPLE + Example2 +#> +function Get-ITDAzureRMIPs +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Param1 help description + [Parameter(Mandatory=$true, Position=0)] + [String] + $OutputPath + ) + + Begin + { + $WindowsIPs = "" + $LinuxIPs = "" + $OutFileWin = $OutputPath + "\AzureWin.txt" + $OutFileLin = $OutputPath + "\AzureLin.txt" + } + Process + { + Login-AzureRMAccount + + $Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} + foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } + } + + Login-AzureRMAccount -EnvironmentName AzureUSGovernment + + $Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} + foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } + } + + If ($WindowsIPs -ne "") {$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline} + If ($LinuxIPs -ne "") {$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline} + } + End + { + } +} + + +function Set-ITDAzureRMResourceGroupTags +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Resouce Group + [String] + $ResourceGroup, + + # Tag Hash Table + [HashTable] + $TagHashTable, + + # Input File + [String] + $InputFile + ) + Begin + { + } + Process + { + If($InputFile) + { + $filetable = Import-CSV -Path $InputFile + foreach($record in $filetable) + { + $TagHashTable = @{} + $TagHashTable.Add("Environment",$record.Environment) + $TagHashTable.Add("Platform",$record.Platform) + $TagHashTable.Add("RequestID",$record.RequestID) + $TagHashTable.Add("Division",$record.Division) + $TagHashTable.Add("ApplicationName",$record.ApplicationName) + $TagHashTable.Add("ChargeCode",$record.ChargeCode) + $TagHashTable.Add("Department",$record.Department) + + Set-AzureRmContext $record.Subscription + Set-ITDAzureRMResourceGroupTags -ResourceGroup $record.ResourceGroup -TagHashTable $TagHashTable + } + Return + } + + + + #Get Current Tags from Resource Group + $GroupTags = (Get-AzureRmResourceGroup -Name $ResourceGroup).Tags + + #Identify Duplicate Tags. Remove Duplicates from Original Tags in Case of Conflict + $DuplicateItems = $GroupTags.Keys | Where-Object {$TagHashTable.ContainsKey($_)} + If ($DuplicateItems) { + ForEach ($DuplicateKey in $DuplicateItems){ + $GroupTags.Remove($DuplicateKey) + } + } + + #Merge Hashtables and Write Table back to Resource Group + $GroupTags += $TagHashTable + Set-AzureRmResourceGroup -Name $ResourceGroup -Tag $GroupTags + + #Get All Resources in the Resource Group + $Resources = Get-AzureRmResource | Where-Object {$_.ResourceGroupName -eq $ResourceGroup -and $_.ResourceType -notmatch "Microsoft.Compute/virtualMachines/extensions"} + ForEach ($Resource in $Resources){ + $ResourceTags = $Resource.Tags + + #Identify Duplicate Tags. Remove Duplicates from Original Tags in Case of Conflict + $DuplicateItems = $ResourceTags.Keys | Where-Object {$TagHashTable.ContainsKey($_)} + If ($DuplicateItems) { + ForEach ($DuplicateKey in $DuplicateItems){ + $ResourceTags.Remove($DuplicateKey) + } + } + + #Merge Hashtables and Write Table back to Resource + $ResourceTags += $TagHashTable + Set-AzureRMResource -ResourceID $Resource.ResourceID -Tag $ResourceTags -Confirm:$false -Force + + } + } + End + { + } +} + +function Set-ITDAzureRMResourceGroupTagsRefresh +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Resouce Group + [String] + $ResourceGroup + ) + Begin + { + $TagHashTable = @{} + $TagHashTable = (Get-AzureRMResourceGroup -Name $ResourceGroup ).Tags + } + Process + { + Set-ITDAzureRMResourceGroupTags -ResourceGroup $ResourceGroup -TagHashTable $TagHashTable + } + End + { + } +} + + +function New-ITDAzureRMPolicyDefinition +{ + [OutputType([int])] + Param + ( + # Resource Group + [Parameter(Mandatory=$true, Position=0)] + [Array] + $Environments, + + # Policy Name Prefix + [Parameter(Mandatory=$true, Position=1)] + [String] + $prefix, + + # Policy Name Suffix + [Parameter(Mandatory=$true, Position=2)] + [String] + $suffix, + + # Policy in String Format (If...Then Components) + [Parameter(Mandatory=$true,Position=3)] + [String] + $Policy + + ) + Begin + { + } + Process + { + Foreach ($environment in $Environments){ + Set-AzureRMContext $environment + $policyname = $prefix + $environment + $suffix + New-AzureRmPolicyDefinition -Name $policyname -Policy $Policy + } + } + End + { + } +} + +function Find-ITDAzureRMUntaggedResources +{ + [OutputType([int])] + Param + ( + # Resource Group + [Parameter(Mandatory=$false, Position=0)] + [String] + $TagName + ) + Begin + { + $subscriptions = @() + $untaggedresources = @() + } + Process + { + #$subscriptions = Get-AzureRMSubscription | WHere-Object {$_.name -ne "sandbox"} + $subscriptions = Get-AzureRMSubscription + + Foreach ($subscription in $subscriptions){ + Set-AzureRMContext $subscription + $resources = Get-AzureRMResource + ForEach ($resource in $resources){ + If ($resource.tags -ne $null){ + If (($resource.tags.contains("Department") -eq $false) -or ($resource.tags.contains("ApplicationName") -eq $false) -or ($resource.tags.contains("Environment") -eq $false) -or ($resource.tags.contains("RequestID") -eq $false)){ + $untaggedresources += $resource + } + } + Else { + $untaggedresources += $resource + } + } + } + $untaggedresources | Select Name, ResourceGroupName, SubscriptionID | Sort-Object SubscriptionID, ResourceGroupname, Name | Format-Table + } + End + { + } +} + +<# +.Synopsis + Creates an Azure VM. +.DESCRIPTION + Long description +.EXAMPLE + New-ITDAzureRMVM -VMName itdcdtest -VMSubscription npd01 -VMEnvironment tst -VMOwner shared -VMFunction cdtesting -VMSize Standard_A2 -VMOS Windows -VMPublisher MicrosoftWindowsServer -VMOffer WindowsServer -VMSku 2016-Datacenter -VMVNetName vnet-tst-npd01-001 -VMSubnet "sn-10.21.20.0_28" -VMLocation centralUS -VMIP "10.21.20.10" +.EXAMPLE + +#> +function New-ITDAzureRMVM +{ + [CmdletBinding()] + Param + ( + # VM Computer Name (FQDN) + [Parameter(Mandatory=$true, Position=0)] + [String] + $VMFQDN, + + # VM Subscription (tst,prd,dr) + [Parameter(Mandatory=$true)] + [string] + $VMSubscription, + + # Environment (tst,prd,dr) + [Parameter(Mandatory=$true)] + [string] + $VMEnvironment, + + # Owner (infra,shared,ITD,DHS,etc) + [Parameter(Mandatory=$true)] + [string] + $VMOwner, + + # Function (testdc, POC, etc) + [Parameter(Mandatory=$true)] + [string] + $VMFunction, + + #[Parameter(Mandatory=$true)] + [string] + $ResourceGroupIndexNumber, + + # Azure VM Size + [Parameter(Mandatory=$true)] + [string] + $VMSize, + + # Azure OS (Windows or Linux) + [Parameter(Mandatory=$true)] + [string] + $VMOS, + + # Availability Set + [switch] + $VMAS, + + # Availability Set Tier + [string] + $VMASTier, + + # Availability Zone + [ValidateSet(1,2,3)] + [int] + $VMAvailZone, + + # Azure Publisher + [string] + $VMPublisher, + + # Azure Offer + [string] + $VMOffer, + + # Azure Sku + [string] + $VMSku, + + # Azure vNet + [Parameter(Mandatory=$true)] + [string] + $VMVNetName, + + # Azure Subnet + [Parameter(Mandatory=$true)] + [string] + $VMSubnet, + + # Azure Location + [Parameter(Mandatory=$true)] + [string] + $VMLocation, + + # Azure Private IP + [Parameter(Mandatory=$true)] + [string] + $VMIP, + + [Parameter(Mandatory=$true)] + [PSCredential] + $VMCredential + ) + Begin + { + $VMName = $VMFQDN.Split('.')[0] + $VMIndexNumber = "001" + $VMIPConfigName = "ipconfig-$VMName-$VMEnvironment" + $VMNicName = "nic-$VMName-$VMEnvironment" ###### + $VMObjectName = "vm-$VMName-$VMEnvironment" + $ResourceGroup = "rg-$VMOwner-$VMFunction-$VMEnvironment" + If($ResourceGroupIndexNumber){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndexNumber"} + $VMDiagStorageAcct = "sa" + $VMOwner + $VMFunction + "diag" + $VMEnvironment + $VMOSDiskName = "vm-$VMName-os-$VMEnvironment" + + If($VMASTier) + { + $VMASName = "as-$VMOwner-$VMFunction-$VMASTier-$VMEnvironment" + } + Else + { + $VMASName = "as-$VMOwner-$VMFunction-$VMEnvironment" + } + + $ResGroupExist = "" + + Write-Verbose "Checking Storage Account Length" + If (($VmDiagStorageAcct.Length) -gt 24){ + Write-Verbose "Storage Account Length is too long. Truncating function...." + $TruncateCharacters = $VmDiagStorageAcct.Length - 24 + $ShortVMFunction = $VMFunction.Substring(0, ($VMFunction.length) - $TruncateCharacters) + $VMDiagStorageAcct = "sa" + $VMOwner + $ShortVMFunction + "diag" + $VMEnvironment + } + + If (($VmDiagStorageAcct.Length) -gt 24){ + Write-Verbose "Storage Account Length is too long after truncating. Terminating Build" + Return + } + + Write-Verbose "Verifying Applicable Inputs are Lowercase" + $VMIPConfigName = $VMIPConfigName.ToLower() + $VMNicName = $VMNicName.ToLower() + $VMObjectName = $VMObjectName.ToLower() + $ResourceGroup = $ResourceGroup.ToLower() + $VMDiagStorageAcct = $VMDiagStorageAcct.ToLower() + $VMOSDiskName = $VMOSDiskName.ToLower() + } + Process + { + Set-AzureRMContext $VMSubscription + + Write-Verbose "Creating Resource Group if it doesn't exist" + $ResGroupExist = Get-AzureRMResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue + + If (!($ResGroupExist)) + { + New-AzureRmResourceGroup -Name $ResourceGroup -Location $VMLocation + } + + Write-Verbose "Checking Storage Account Availability in Subscription" + If (!(Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $VMDiagStorageAcct})) + { + If ((Get-AzureRmStorageAccountNameAvailability -Name $VMDiagStorageAcct).NameAvailable -eq $True) + { + + New-AzureRmStorageAccount -Name $VMDiagStorageAcct -Location $VMLocation -ResourceGroupName $ResourceGroup -SkuName "Standard_LRS" -EnableHttpsTrafficOnly $true + #Start-Sleep -Seconds 5 + Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct | Update-AzureRmStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None + #Update-AzureRmStorageAccountNetworkRuleSet -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct -DefaultAction Deny -Bypass None + Add-AzureRmStorageAccountNetworkRule -ResourceGroupName $ResourceGroup -AccountName $VMDiagStorageAcct -IPAddressOrRange "165.234.248.3" + } + Else + { + Write-Verbose "Storage Account already exists. Re-run with a valid storage account" + Return + } + } + + Write-Verbose "Evaluating Availability Set" + If($VMAS) + { + Write-Verbose "Checking for existing Availability Set" + $VMASExist = Get-AzureRMAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -ErrorAction SilentlyContinue + If($VMASExisting) + { + $VMASID = $VMASExist.id + } + Else + { + New-AzureRMAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -Location $VMLocation -PlatformFaultDomainCount 3 -PlatformUpdateDomainCount 5 -Sku Aligned + $VMASID = (Get-AzureRMAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName).id + } + } + + Write-Verbose "Preparing Network Config" + $VNet = (Get-AzureRmVirtualNetwork | where {$_.Name -eq $VMVNetName}) + $VNetID = $VNet.id + $Subnet = ($VNet.Subnets | where {$_.Name -eq $VMSubnet}) + $SubnetName = $Subnet.name + $SubnetID = $Subnet.id + + Write-Verbose "Creating IPConfig and NIC" + $IPConfig = New-AzureRmNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $VMIP -PrivateIpAddressVersion IPv4 -Subnet $Subnet + $VMNIC = New-AzureRmNetworkInterface -IpConfigurationName $IPConfig -Location $VMLocation -Name $VMNICName -ResourceGroupName $ResourceGroup -SubnetId $SubnetID + $VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static" + $VMNIC.IpConfigurations[0].PrivateIpAddress = $VMIP + Set-AzureRmNetworkInterface -NetworkInterface $VMNIC + + Write-Verbose "Building VM Config" + If($VMAS) + { + $vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize -AvailabilitySetId $VMASID + } + Else + { + If($VMAvailZone) + { + Write-Verbose "AvailZone $VMAvailZone" + $vmConfigParams = @{ + VMName = $VMObjectName + VMSize = $VMSize + Zone = $VMAvailZone + } + } + Else + { + Write-Verbose "No AvailZone" + $vmConfigParams = @{ + VMName = $VMObjectName + VMSize = $VMSize + } + } + #$vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize + $vmConfig = New-AzureRmVMConfig @vmConfigParams + } + + + + $vmConfig | Set-AzureRmVMOSDisk -Name $VMOSDiskName -CreateOption FromImage + If($VMOS -eq "Windows") + { + $vmConfig | Set-AzureRmVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential + $vmConfig | Set-AzureRmVMSourceImage -PublisherName $VMPublisher -Offer $VMOffer -Skus $VMSku -Version latest + } + If($VMOS -eq "Linux") + { + $vmConfig | Set-AzureRmVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $VMCredential + Switch($VMSubscription) + { + #"npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} + #"infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} + #"prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-002"} + + "npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103"} + "infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403"} + "prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003"} + } + } + + $vmConfig | Add-AzureRmVMNetworkInterface -Id $VMNIC.ID + $vmConfig | Set-AzureRmVMBootDiagnostics -Enable -ResourceGroupName $ResourceGroup -StorageAccountName $VMDiagStorageAcct + + Write-Verbose "Creating VM" + New-AzureRMVM -VM $vmConfig -ResourceGroupName $resourceGroup -Location $VMLocation -DisableBginfoExtension -AsJob + + + } + End + { + } +} + +function Remove-ITDAzureRMResourceGroupTags +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Input File + [Parameter(Mandatory=$true)] + [String] + $InputFile, + + # Azure Tag to Remove + [Parameter(Mandatory=$true)] + [string] + $RemoveTag + ) + Begin + { + } + Process + { + If($InputFile) + { + $filetable = Import-CSV -Path $InputFile + foreach($record in $filetable) + { + $ResTag = $record.ResourceGroup + $SubTag = $record.Subscription + + Set-AzureRmContext $SubTag + $GroupTags = (Get-AzureRmResourceGroup -Name $ResTag).Tags + $GroupTags.Remove($RemoveTag) + Set-AzureRmResourceGroup -Name $ResTag -Tag $GroupTags + + $Resources = Get-AzureRmResource | Where-Object {$_.ResourceGroupName -eq $ResTag} + ForEach ($Resource in $Resources) + { + $ResourceTags = $Resource.Tags + $GroupTags.Remove($RemoveTag) + Set-AzureRMResource -ResourceID $Resource.ResourceID -Tag $ResourceTags -Confirm:$false -Force + } + } + Return + } + + } + End + { + } +} + +<# +.Synopsis + Create new Azure data disk, and attach to the specified VM +.DESCRIPTION + Create new Azure data disk, and attach to the specified VM. + - Determines ResourceGroup where disk will be created, the name of the disk, and the LUN ID the disk will use. + - SizeGB must be unique for each disk attached to a virtual machine. If the SizeGB parameter is not unique, new size will be automatically determined. +.EXAMPLE + Add-ITDAzureRMNewDataDisk -VMName vm-itdvm-tst -SizeGB 32 +#> +function Add-ITDAzureRMNewDataDisk +{ + [CmdletBinding()] + Param + ( + [string] + $VMName, + + [int[]] + $SizeGB + ) + + Begin + { + $search=@() + $Hostname=$VMName.split('-')[1] + $Environment=$VMName.split('-')[2] + + Get-AzureRmSubscription | ForEach-Object{ + $Subscription=$_ + Set-AzureRmContext $_ | Out-Null + $search += Get-AzureRmVM | Where-Object Name -eq $VMName | select *,@{n='SubscriptionName';e={$Subscription.Name}} + } + } + Process + { + If($search.count -eq 1) + { + Set-AzureRmContext $search.SubscriptionName + $ResourceGroup = $search.ResourceGroupName.ToLower() + $Location = (Get-AzureRmResourceGroup -Name $ResourceGroup).Location + $VM = Get-AzureRmVM -Name $VMName -ResourceGroupName $ResourceGroup + $Zone=$VM.Zones + + + ForEach($Size in $SizeGB) + { + $ExistingDisks = @($VM.StorageProfile.DataDisks | select *,@{n='ItdId';e={[int]($_.Name -replace "vm-$hostname-app-$environment-")}}) + + $NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | select -First 1).ItdId + 1 + $NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000") + $NewDiskName="vm-$Hostname-app-$Environment-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001 + + $LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1 + + $count=0 + If($ExistingDisks) + { + while ($Size -match $ExistingDisks.DiskSizeGB) + { + $count++ + Write-Warning "SizeGB: $Size, Count: $count" + If($count -ge 11) + { + Write-Error "Disk size not available" -ErrorAction Stop + } + Else + { + $Size = $Size - 1 + } + } + } + + Write-Warning "SizeGB: $Size, Count: $count" + + $AzureRmDiskConfigParams=@{ + DiskSizeGB = $Size + Location = $Location + CreateOption = "Empty" + SkuName = "Premium_LRS" + } + + If($Zone) + { + Write-Verbose "VM is located in Zone $Zone" + $AzureRmDiskConfigParams += @{Zone = $Zone} + } + #$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS + $DiskConfig = New-AzureRmDiskConfig @AzureRmDiskConfigParams + + If(!(Get-AzureRmDisk -ResourceGroupName $ResourceGroup -DiskName $NewDiskName -ErrorAction SilentlyContinue)) + { + $NewDisk = New-AzureRmDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroup + + $VM = Add-AzureRmVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly + Update-AzureRmVM -VM $VM -ResourceGroupName $ResourceGroup -AsJob + } + } + } + Else + { + Write-Error "Search count invalid" -ErrorAction SilentlyContinue + } + } + End + { + } +} + +<# +.SYNOPSIS + Provision Windows or RHEL VM +.DESCRIPTION + Create Azure IaaS VM, to ITD standards: + *** Requires resource group to be created before running + *** Required DNS record for FQDN. + - Create Storage Account for Resource Group if missing + - Create VM + - Scaled to hardware specifications, B-class for tst, D-class for prd + -Size parameter exists if above restrictions must be overridden + - NIC created, IP pulled from DNS + - Auto decide VLAN/subnet based on Environment parameter + - Operating system chosen by user + - Auto generate PasswordState record (ITDActiveDirectory module required) with GeneratePassword parameter + - Utilize VMCredential parameter to set local administrator (itdadmin) password +.EXAMPLE + New-ITDAzureVM -ComputerName itddc20.nd.gov -CPU 2 -Memory 8 -AppName "Infra-Active Directory" -Environment "prd" -OperatingSystem WS2012R2 -GeneratePassword +.EXAMPLE + New-ITDAzureVM -ComputerName itddc21.nd.gov -CPU 2 -Memory 8 -AppName "Infra-Active Directory" -Environment "prd" -OperatingSystem WS2012R2 -VMCredential (Get-Credential) +#> +function New-ITDAzureVM +{ + [CmdletBinding()] + Param + ( + [Parameter(Mandatory=$true)] + [string] + $ComputerName, + + [Parameter(Mandatory=$true)] + [int] + $CPU, + + [Parameter(Mandatory=$true)] + [int] + $Memory, + + [Parameter(Mandatory=$true)] + [string] + $AppName, + + [Parameter(Mandatory=$true)] + [ValidateSet("tst","prd")] + [string] + $Environment, + + [string] + $ResourceGroupIndex, + + [Parameter(Mandatory=$true)] + [ValidateSet("WS2012R2","WS2016","WS2019","WS2022","W10v1803","W10v1809","RHEL7.4")] + [string] + $OperatingSystem, + + [ValidateSet(1,2,3)] + [int] + $AvailZone, + + [Parameter(ParameterSetName="PasswordGenerate")] + [switch] + $GeneratePassword, + + [Parameter(ParameterSetName="PasswordEnter")] + [PSCredential] + $VMCredential + + #[string] + #$VMSizeOverride, + + #[ValidateSet('infra01','npd01','prd01')] + #[string] + #$SubscriptionOverride + ) + + begin + { + $location="centralus" + $username = "itdadmin" + + $VMOwner = $AppName.split('-')[0].ToLower() + $VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " " + $Name=$ComputerName.Split('.')[0] + $IPAddress = (Resolve-DnsName -Name $ComputerName -ErrorAction Stop).IpAddress + $ResourceGroup = "rg-$VMOwner-$VMFunction-$Environment" + If($ResourceGroupIndex){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndex"} + $VMName = "vm-$Name-$Environment" + } + + process + { + + switch ($Environment) + { + tst + { + $VMSizeFilter="*_B*s*" + $Subscription = "npd01" + $VNet="vnet-npd01-001" + $VNetSubnet="sn-shared-zerotrust-npd-10.21.8.0_22" + } + prd + { + $VMSizeFilter="*_D*s*" + $Subscription = "prd01" + $VNet="vnet-prd01-001" + $VnetSubnet="sn-shared-zerotrust-prd-10.21.12.0_22" + } + Default + { + Write-Error "Environment failed" -ErrorAction Stop + } + } + + switch ($OperatingSystem) + { + 'WS2012R2' + { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2012-R2-Datacenter" + $PSList = "CSRC" + } + 'WS2016' + { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2016-Datacenter" + $PSList = "CSRC" + } + 'WS2019' + { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2019-Datacenter" + $PSList = "CSRC" + } + 'WS2022' + { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2022-Datacenter" + $PSList = "CSRC" + } + 'W10v1803' + { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsDesktop" + $Offer = "Windows-10" + $sku = "rs4-pro" + $PSList = "CSRC" + } + 'W10v1809' + { + Write-Error "W10v1809 not available" -ErrorAction Stop + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsDesktop" + $Offer = "Windows-10" + $sku = "rs5-pro" + $PSList = "CSRC" + } + 'RHEL7.4' + { + $VMOS = "Linux" + $Publisher = $null + $Offer = $null + $sku = $null + $PSList = "Linux" + } + } + + If ($GeneratePassword) + { + Write-Verbose "GeneratePassword true" + try + { + $TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" + Write-Warning "[$ComputerName]:$TimeStamp - Password generation " + #$password = ConvertTo-SecureString (New-ITDLocalAdminPasswordstateRecord -ComputerName $ComputerName -Azure -PasswordstateList $PSList -Credential $AdminCred).Password -AsPlainText -Force + $password = ConvertTo-SecureString (New-ITDPasswordstateRecord -Title $ComputerName -Description "Local Admin" -PSList $PSList -GeneratePassword -Username itdadmin -ReturnPassword).Password -AsPlainText -Force + } + catch + { + Write-Error "GeneratePassword failed, process manually" -ErrorAction Stop + } + } + Else + { + Write-Verbose "GeneratePassword false" + $password = $VMCredential.Password + } + + $VMCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password + + $VMSize = Get-AzureRmVMSize -Location $location | ` + Where-Object Name -Like "$VMSizeFilter" | ` + Where-Object {$_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024)*0.5 } | ` + Where-Object Name -NotMatch "_Promo" | ` + Sort-Object NumberOfCores,MemoryInMB | ` + Select-Object -First 1 + + If($SubscriptionOverride) + { + $Subscription = $SubscriptionOverride + } + If($VMSizeOverride) + { + $VMSize = Get-AzureRmVMSize -Location $location | ` + Where-Object Name -Like $VMSizeOverride + } + + $NewITDAzureRMVMParams=@{ + VMFQDN = $ComputerName + VMSubscription = $Subscription + VMEnvironment = $Environment + VMOwner = $VMOwner + VMFunction = $VMFunction + VMSize = $VMSize.Name + VMOS = $VMOS + VMPublisher = $Publisher + VMOffer = $Offer + VMSku = $sku + VMVnetName = $VNet + VMSubnet = $VNetSubnet + VMLocation = $location + VMIP = $IPAddress + VMCredential = $VMCredential + } + + If($AvailZone){$NewITDAzureRMVMParams += @{VMAvailZone = $AvailZone}} + If($ResourceGroupIndex){$NewITDAzureRMVMParams += @{$ResourceGroupIndexNumber = $ResourceGroupIndex}} + <# + Write-Warning $NewITDAzureRMVMParams.VMFQDN + Write-Warning $NewITDAzureRMVMParams.VMSubscription + Write-Warning $NewITDAzureRMVMParams.VMEnvironment + Write-Warning $NewITDAzureRMVMParams.VMOwner + Write-Warning $NewITDAzureRMVMParams.VMFunction + Write-Warning $NewITDAzureRMVMParams.VMSize + Write-Warning $NewITDAzureRMVMParams.VMOS + Write-Warning $NewITDAzureRMVMParams.VMPublisher + Write-Warning $NewITDAzureRMVMParams.VMOffer + Write-Warning $NewITDAzureRMVMParams.VMSku + Write-Warning $NewITDAzureRMVMParams.VMVnetName + Write-Warning $NewITDAzureRMVMParams.VMSubnet + Write-Warning $NewITDAzureRMVMParams.VMLocation + Write-Warning $NewITDAzureRMVMParams.VMIP + Write-Warning $NewITDAzureRMVMParams.VMCredential + Write-Warning $NewITDAzureRMVMParams.VMAvailZone + #> + + New-ITDAzureRMVM @NewITDAzureRMVMParams + + <# + New-ITDAzureRMVM -VMFQDN $ComputerName ` + -VMSubscription $Subscription ` + -VMEnvironment $Environment ` + -VMOwner $VMOwner ` + -VMFunction $VMFunction ` + -VMSize $VMSize.Name ` + -VMOS $VMOS ` + -VMPublisher $Publisher ` + -VMOffer $Offer ` + -VMSku $Sku ` + -VMVNetName $VNet ` + -VMSubnet $VNetSubnet ` + -VMLocation $location ` + -VMIP $IPAddress ` + -VMCredential $VMCredential ` + -Verbose #> + + # wait for provisioning completion + do { + Start-Sleep -Seconds 15 + } while ( (Get-AzureRmVM -ResourceGroupName $ResourceGroup | Where-Object Name -Match $Name).ProvisioningState -eq "Creating") + + # check NIC + $nic=Get-AzureRmNetworkInterface -ResourceGroupName $ResourceGroup | Where-Object Name -Match $Name + $nic.IpConfigurations[0].PrivateIpAllocationMethod = "Static" + $nic.IpConfigurations[0].PrivateIpAddress = $IPAddress + Set-AzureRmNetworkInterface -NetworkInterface $nic + + #customize + switch ($VMOS) + { + 'Windows' + { + Invoke-AzureRmVMRunCommand -VMName $VMName ` + -ResourceGroupName $ResourceGroup ` + -CommandId 'RunPowerShellScript' ` + -ScriptPath "S:\Distributed Systems\Systems\Azure\Scripts\WindowsCustomization.ps1" ` + -AsJob + } + 'Linux' + { + + } + Default + { + + } + } + } + end + { + + } +} + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function New-ITDAzureRMResourceGroup +{ + [CmdletBinding()] + Param + ( + [string[]] + $AppName, + + [ValidateSet('prd','tst','infra')] + [string[]] + $Environment, + + [ValidateSet('centralus')] + [string] + $Location, + + [ValidateSet('VM','Network')] + [string] + $Ownership + ) + + begin + { + $Subscriptions=Get-AzureRmSubscription + } + + process + { + ForEach($App in $AppName) + { + ForEach($Env in $Environment) + { + $VMOwner = $App.split('-')[0].ToLower() + $VMFunction = (($App -replace "$VMOwner-") -replace "-").ToLower() -replace " " + $ResourceGroupName = "rg-$VMOwner-$VMFunction-$Env" + + Write-Verbose "Resource Group Name: $ResourceGroupName" + + $Tags = @{ + "ApplicationName" = $AppName; + "Environment" = $Environment; + } + + switch ($Env) + { + 'infra' + { + $SubscriptionsToUse=@("infra01","infradr01") + } + 'prd' + { + $SubscriptionsToUse=@("prd01","prddr01") + } + 'tst' + { + $SubscriptionsToUse=@("tst01","tstdr01") + } + Default + { + Write-Error "invalid Environment" -ErrorAction Stop + } + } + + ForEach($Sub in $SubscriptionsToUse) + { + Set-AzureRmContext -Context ($Subscriptions | Where-Object Name -eq $Sub) + + Write-Verbose "Creating Resource Group $ResourceGroupName" + New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location -Tag $Tags + + Write-Verbose "Setting $Ownership Permissions on Resource Group $ResourceGroupName" + Set-ITDAzureRMResourceGroupAssignment -Ownership $Ownership -ResourceGroup $ResourceGroupName + } + } + } + + } + + end + { + } +} + + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Find-ITDAzureRMVM +{ + [CmdletBinding()] + Param + ( + [string] + $VMName + ) + + begin + { + + } + + process + { + $search=@() + $Hostname=$VMName.split('-')[1] + $Environment=$VMName.split('-')[2] + + Get-AzureRmSubscription | ForEach-Object{ + $Subscription=$_ + Set-AzureRmContext $_ | Out-Null + $search += Get-AzureRmVM | Where-Object Name -eq $VMName | select *,@{n='SubscriptionName';e={$Subscription.Name}} + } + + If(@($search).count -eq 1) + { + Write-Output $search + } + else + { + $count = $search.count + Write-Error ($count + "VMs found") + } + } + end + { + + } +} + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Set-ITDAzureRmVMBackup +{ + [CmdletBinding()] + Param + ( + [string[]] + $VMName + ) + + begin + { + + } + + process + { + ForEach($name in $VMName) + { + $Vault = $null + $BackupPolicy = $null + + $vm = Find-ITDAzureRMVM -VMName $name -ErrorAction Stop + + Set-AzureRmContext $vm.SubscriptionName + $Vault = Get-AzureRmRecoveryServicesVault -Name rs-infra-azbackup-prd-100 + Set-AzureRmRecoveryServicesVaultContext -Vault $Vault + $BackupPolicy = Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name "DefaultPolicy" + Enable-AzureRmRecoveryServicesBackupProtection -Policy $BackupPolicy -Name $$vm.Name -ResourceGroupName $vm.ResourceGroupName + } + } + + end + { + + } +} + +function New-ITDAzureRMResourceGroupAll +{ + [CmdletBinding()] + [Alias()] + [OutputType([int])] + Param + ( + # Subscription for the Resource Group + [Parameter(Mandatory=$true)] + [String] + $Subscription, + + # Resource Group Name + [Parameter(Mandatory=$true)] + [string] + $Name, + + # Ownership -- VM or Network + [Parameter(Mandatory=$true)] + [String] + $Ownership, + + # Azure Region + [Parameter(Mandatory=$true)] + [string] + $Location, + + # Application Name + [Parameter(Mandatory=$true)] + [string] + $ApplicationName + ) + + Begin + { + Set-AzureRmContext $Subscription + $TagHashTable = @{} + $ApplicationNameKey = "ApplicationName" + $TagHashTable.Add($ApplicationNameKey, $ApplicationName) + } + Process + { + New-AzureRmResourceGroup -Name $Name -Location $Location -Tag $TagHashTable + Set-ITDAzureRMResourceGroupAssignment -Ownership $Ownership -ResourceGroup $Name + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_CS/ITDAzureRM/NewVMExistingDisk.ps1 b/_NDGOV_CS/ITDAzureRM/NewVMExistingDisk.ps1 new file mode 100644 index 0000000..df3e529 --- /dev/null +++ b/_NDGOV_CS/ITDAzureRM/NewVMExistingDisk.ps1 @@ -0,0 +1,102 @@ +#20190204 - 2nd comment, this one in master branch +#7th comment + +# copy disk example +<# +set-azurermcontext -Subscription npd01 +$disk = Get-AzureRmDisk -ResourceGroupName rg-doh-intranetconnections-tst -DiskName vm-itddohict1-app-tst-001 +set-azurermcontext -Subscription prd01 +$newdisk = New-AzureRmDiskConfig -SourceResourceId $disk.Id -Location centralus -CreateOption Copy +New-AzureRmDisk -ResourceGroupName rg-doh-intranetconnections-prd -DiskName vm-itddohicp1-app-prd-001 -Disk $newdisk +#> + + + + +$computername="itdadfsldt1" +#Provide the subscription Id +$subscriptionId = '76297098-764c-43de-8525-c9fda1b237be' + +#Provide the name of your resource group +$resourceGroupName ='rg-infra-adfs-tst' + +Set-AzureRmContext -Subscription infra01 +$disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName "dev_sda-vm_itdadfsldt1_tst" +Set-AzureRmContext -Subscription npd01 +$newdisk = New-AzureRmDiskConfig -SourceResourceId $disk.Id -Location centralus -CreateOption Copy +New-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName vm-$computername-os-tst -Disk $newdisk + +#Provide the name of the OS disk that will be created using the snapshot +$osDiskName = "vm-$computername-os-tst" + +#Provide the name of the virtual machine +$virtualMachineName = "vm-$computername-tst" + +$nicName = "nic-$computername-tst-101" + +#Provide the size of the virtual machine +#e.g. Standard_DS3 +#Get all the vm sizes in a region using below script: +#e.g. Get-AzureRmVMSize -Location westus +$virtualMachineSize = 'Standard_A1' + +#Set the context to the subscription Id where Managed Disk will be created +#Select-AzureRmSubscription -SubscriptionId $SubscriptionId +Set-AzureRmContext -Subscription npd01 +<# +$resourceGroupName="rg-doh-intranetconnections-prd" +$osDiskName="vm-itddohicp1-os-prd" +$virtualMachineName="vm-itddohicp1-prd" +$virtualMachineSize="Standard_B2ms" +$nicName="nic-itddohicp1-prd" +#> + +$disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $osDiskName + +#Initialize virtual machine configuration +$VirtualMachine = New-AzureRmVMConfig -VMName $virtualMachineName -VMSize $virtualMachineSize + +#Use the Managed Disk Resource Id to attach it to the virtual machine. Please change the OS type to linux if OS disk has linux OS +$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $disk.Id -CreateOption Attach -Linux + +$nic = Get-AzureRmNetworkInterface -ResourceGroupName $resourcegroupname -Name $nicName + +$VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $nic.Id + +#Create the virtual machine with Managed Disk +New-AzureRmVM -VM $VirtualMachine -ResourceGroupName $resourceGroupName -Location centralus + + + + + + + + +Set-AzureRmContext -Subscription infra01 +$disks = Get-AzureRmDisk -ResourceGroupName rg-infra-adfs-tst -ov npddisks +Set-AzureRmContext -Subscription npd01 +ForEach($d in $disks) +{ + $newdisk=$null + $computername=$null + + + $computername = $d.name.split('_')[2] + If($d.name -like "*sda*") + { + $newname = "vm-$computername-os-tst" + } + If($d.name -like "*sdb*") + { + $newname = "vm-$computername-app-tst-101" + $newdisk = New-AzureRmDiskConfig -SourceResourceId $d.Id -Location centralus -createoption Copy + New-AzureRmDisk -ResourceGroupName rg-infra-adfs-tst -DiskName $NewName -Disk $newdisk + } +} +<# +$disk = Get-AzureRmDisk -ResourceGroupName rg-infra-adfs-tst -DiskName dev_sdb-vm_itdadfsintldt1_tst +set-azurermcontext -Subscription npd01 +$newdisk = New-AzureRmDiskConfig -SourceResourceId $disk.Id -Location centralus -CreateOption Copy +New-AzureRmDisk -ResourceGroupName rg-infra-adfs-tst -DiskName vm-itdadfsldt1-app-tst-001 -Disk $newdisk +#> \ No newline at end of file diff --git a/_NDGOV_CS/ZM1/README.md b/_NDGOV_CS/ZM1/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_CS/ZM1/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_CS/ZM1/first-playbook.yml b/_NDGOV_CS/ZM1/first-playbook.yml new file mode 100644 index 0000000..02dbbf3 --- /dev/null +++ b/_NDGOV_CS/ZM1/first-playbook.yml @@ -0,0 +1,12 @@ +--- + - name: zm test + hosts: itdscmt1.nd.gov + tasks: + - name: run command + win_command: netstat + - name: Run PowerShell script with parameter + ansible.windows.win_powershell: + script: | + New-Item D:\{{ ComputerName }}.txt + Write-Output "{{ ComputerName }}" + diff --git a/_NDGOV_CS/cecogdill/snowSample.zip b/_NDGOV_CS/cecogdill/snowSample.zip new file mode 100644 index 0000000000000000000000000000000000000000..7adf5e92695660136d2370ba3abe6040cee58dab GIT binary patch literal 6086 zcmZ`-RZtwC|5}cre26qMzGB^ZCaCditJA=Co?k>S0xO)h?`FE@K z-dnYM&cj#VsqWYAKCLW|giHtk0MG$*dV(5nGt`p^(EtE?8UO(E@2izFM9t3LjorcH zL|aAamjJ%cS=BkpkNnnE;@fIf7xBRMU(Vqg33CU%xr4ohH*tcXV@x$Cb6>w! z`Ox!zc6V|siqF@Q}H7J6Nv)Em%-C<_rz7aV`p+zDoVJ(?0id7Zs ztT>SwF84Wa`T{U9LUff(1jd{EKq47zPC#6hkSpPOOl)3%Fv9R*QO zCV{8e8A%mCIg0%8?=g-s&@a8TcrIXO0cb#$vK(!$xM(G!x6JTeoi;gG&BpI4Jjy18 z>sr)CxwcJnn$;s?w2+H22Q^fCU36&&w=}QApDVFcZRI!L>) zNT|cV=T=$uR5hxRpPkrtoHl|XqN@qkI%kg=|4VKuJ)uaK!p^Zxfk$E9Z3 zR7aL&xiCYl?==B4LAPVO86r$4Gy0m#b(636rw)@6x47&IV}X9PQkVxj&2keT`=!FO zq|tRme6$8H6dM(HzaNuSpNM5Sg)H>uS8a_rL5b7s>0|Z%9TlVrN% zs9b38P(I894}-pny2#l3w?kq zkVVpfl%`ciB)_NSL%qCmbvaGp*5W5ZuJf}lJ$o&wB+ovl(alk&x>3(RELt|Yugh31 zJI}3pK|%HJ*w8At)AMYU-|A}`+mOh5s?=*fXi-YdBP>1qOneGKiV*~QY3aw1>Sg%9 zAT8pMQdZ?LnA3ZiaGJLyDD1H^6nnKr!sK9N4j+|283vZpK-osD9}-F$B2*|vK_x9# z@@{?{resOTRN0&v;@*QZakd9I6@PA}DmNZIPAJ-|dJ8#-#$x6YR$4Y&GzXNxQ)5`< zE%b^>L5(7M3@*2q)&?A)KS053a9cEemEZ`l2$i-vyXQezS8}yOeM_!Wy8CpU(shs0 z6=UhiyXnEBNeJ4}t|BCG`Khx?r2dmrKUPS^)Wg%MMBqpEGm+v_>p}faAIc8{?66mV ztlbbe98M>$%2aM@L3O9zI(94SAsv<`ZAG}N9{YF{ndG?_*=X??OQ929B8QVI1G5g0pb!_dITZo=d4ZBOwzx);iPq&^(089tt z)>^S`m1mj4s2e#gV;g=B=1Z%(M&!PD@5RiP?exmd;INq!M$*2`{C#yElb}^7rV%08QZ0(mz)H$kX)B(-VDyu}&2k`S^_ z#Ka)vT|O*ccH$iJo=Vz4&a@=LV|`{rX*5JV>DqG`yIBvTV%uTdwo0fY&5N|tXZ_?i zMq)%=WTy~Wv~e38=UWN!^lh%l_DC|vkj=|*oV>h-I+mbf6ScY%!<>V>xm-Ng0?Vr_ zmU?=NRDD2oNC}bL>y1}8HphQ5VeLLe?m-PW@-u_QCKj2N-Auoh0DZ~8fz#$VV#r$q zd)2iMboyz9vdSCiG>a6o2NPQ+-I+(%VeDnGI7;6&n}F6?^t`+6A(H<48*|XU+Enm&SS##3U(u&eh8=IG z)XBxfDYUVF#{NvfNaIY+o9*njmAi37{8`CQgE9IS;u?%ULRa4|EhD#s3GI6Pz+V!F zdNWeiPe*LYO+{E^G|NKH&nP@Y8H3-i!dJ*QPBN>yp%cs1yQm&7?UZhnO0e$C$FFVD znr#;)vg$mg(G6UC23Ql0OJ@St#wmR_9xp+UtLJrC-TtTSvk$&cA5e8k=Z?L^b}|gF z=$fW4-yyyiwv^mN0cmQ(2WJuTHCV<`AxyhiqQilx?nAVl@*ZD6GzMt?=;$#LdL{(M z5E3q?_;UDln3FmB0uY9IZ5$eNH7$@v+l|7XE%O>Q$>A8cp8QRO2p&zu@1!zj+$ zU7M0S0cZBfKJwwNsvm!aS`n&)DC-x4l`_ahInq^h|KKF*4j_ zbWa8(YV8epKK&l80f)<_80LIMA@1(Kso%*!MBvu25)3Z+$sRzB%Q~0_DROJ2l5gsMy|aB(i3{045l+c{1^Nr6uXR3R*cG9_L zc~*gC79Xe7&j^3`aZv@iRy!T}9_;0_!eE}iV`|ys464*s;>Hmr!@IN04iQ^{Ey>ic zoLHI>*emp%FQb=tlNouZtff^C?<`_%igVSfyqDcS@(pEsfCb$mt>g(vh#(K$nCXbu^DbDYhBzkZPSW!2b>R>U z;y;oU-ahYS*ZM>JO#{0lNn*l<`1r(>zU?-V$o#rH%ihVOe-(>O(!l3rxAAd`50~c+ z@(G{bu+T?CGvB3)KC(dOzF4Yyw$sZq8;_O5S{VEIzrRaTEDu}a_mXoZ8bD2=My(JY zDX`g2u2ih4h@|B$9Xu4Y%?z_8FuD!b7U)HY%LN`nq$IZX>6x}g@HMdt!O?R(uPVLh zH%1|*$R-*E#fR5F;Ew%seq{tEH#_Q5bap>j?*}9*s-^@Hl36Kt*?PD#!Q$H7RDUAj z%yr;PUf9jg$*{(CGptH>{^O~I#6=fXm5%9v?RkvG7MDjz2)n(}6d$_^@bp<*ae7!U zYox+gO}}S&O7>)OJ6Kvfc~*1?4!u(@b*U2J)tESMAfb3XIydrg?;7kD0pqP@y^Ub8 zuorGyDeHWaht96)Vy24OM*4sb&PJ}GO`V#WpHbbuK6qb~*LH!2DP4(+iN>D<*2_!n z`zB4UtrnZgUOiQIxhqjFc~qZ8w{^5o?b(m_n_l8GIp8oJx;7^YJsjMPEnM`A!u?M+ zd6Eo}$71z4Jyh0!g#tIL!Ve3u=xJv~uf$n@@cXg`6(1-mD8c)#R{bRb6kqFXSHOm(*HWDtx{( zmRW1LI%8spQIJ-clEqB?xJv!vACJ5Hs^<97a4=Y<;Cw>eVT^!gb5&cDqP?e(TVVZ7IIppBE z(aMrt&MbfGC?AH>`v8L=$=*y~YOOfJSsvl>I#{~bL2xy9PqA9v;^OqXRxC#T#{Hqb9@VRH zYs)OIzUtjAWH>ta*+!BA^(EFUv4xET?(Gt&O#US`U3Z~XE+Bw^O}F~N1bGQZlfdY2 zPV^N_Bqj#|#KmX*(8lNd$aoP#YX}2&Dg@#>kS0;{G8@q#bl>Bs0sw0K6#>sQo-U7v z3q8N$dkmEZhYZ2d(VK>|2F^gHSb+p?-;)jbL%7DRi+uOpU5F(lv!L!3z!Me*!!p{p$gW~%|%t5 z!P+8iwpuwn)DM*DB+EW`XJ-8k$2xYTWYYbcSa}aFtIwy5zsGdz;iJQb9IDu2M`2Z5 z-*+}uXck;4{O6pH&ge>Gd=W?dV}rUfgN21?#oy&hHlDT8xeZ&OPfTKPNu8q;DNQ z9a;|~Bb0VZK9*Vbq#yl${Xs_d!K#&v%F+l~9+%I4ckEX@WCnPYTF@!vxJFlFC<4kG zST}EHX-~1Km6Njp(l;@1keNt0=yj6gbfPd#7~(O=UPg_vQulf(j&3Wd-}R1|i1|Dp z3-cY%X!Y>{{QN$+h7STyNl~r7h*f)>X%2 zEn8exuS(;A2j6`)6+ajxm(q``P5U_5@e~i1Hzhk&de0}K5L2e+b9u)(r5_)kDV){s zYCndF?HHY_HJ04FQrp@w46oTpgYH2Jx@oUaGt}puPZCxKOK({j=7GIeU2(=nu(1N^ zuhR=qW~m%i;8+(y)_vmM#6?m1*81X%nPf~0@T*uUx_^V4`>Ff^Qxkt@Fin+n2=Q~A z$t8M=eO2Yzgn4oK)ke|8_TmcJ2+JYbb9(i@f-KsfqzIP!gVKcj0MkrqdmO7-4O4SW zMf$V*OaHr~TpOLn&+91B>3NV%-5aFvv;^xWY4ig1{*S?{-c7u|X%@O@yG`$?zsPlN zCE-^=gDVG#sP8RwwO8^hV4}Ul@4*ykmGxJ?DuD?bBqe$w-!1rs;ae1jam4+FLuzPG z$u%3MejL5LvFN#4`1Qts7P#aRj3C3eo^e8DO8X$2rfga@B{99QJ6v6Fh3V~#{$>kP zPap83>Ghnh0dh~6Tct874QHpxkfTBe?i}g_0!X8!FXgZWvgAJRXgGU8FMeKWQO241 zy4)|RCsXv>bgU={#6euBOLFxlAtlx~wPYxe82+OYMa$@mu%|_r!9s0jbwRHzF)OmH z7%cEXR9oQp^W#%+?NxX!9?9|6Ui9AHojifVgX&{4SJu7}i8V3ZRb0=_W&5h2%j?hS z)l?%96pYXn;C1j0RY`>H0amz*!kgvS;C@#~Om!xg`Iijw{s#0u0BT2!Yd-SK$yY-m z%XQ?VR)Hm%-x!`lU`l%VO2M#>`(FxXlpX^*L0LiUeu22Vs;Jk*!xFL_i;SQ~p3%l7 zvUca0x8yj;Hr*9>97CgS!l5X?vZ6jRnZS3EgMqLx?jU9@w zzPdmMdtQnnB#tR;1wz{_H-eCqiJ^@h z`tgBLW5Y~d&O9l?xhHRccUQd{c_=zHsw63>8EGYB*l6PJ_3NOD2z@|>2nGXNr0j3@ zB>dLm#?9lm&hw_3^yvzqf$*~wPxm)#vp-^Ltmpvv+nsQ1ON literal 0 HcmV?d00001 diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.All-General/Build/azure-pipelines.yml new file mode 100644 index 0000000..c36d17b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.All-General' + +variables: + major: 1 + minor: 0 + 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.All-General.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.All-General.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Build/build.ps1 new file mode 100644 index 0000000..4237450 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.All-General' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.All-General).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.nuspec b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.nuspec new file mode 100644 index 0000000..a02a027 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.nuspec @@ -0,0 +1,12 @@ + + + + ITD.All-General + $VERSIONHERE$ + Zack Meier + QoL functions that don't fit into another module + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psd1 b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psd1 new file mode 100644 index 0000000..5fa2115 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psd1 @@ -0,0 +1,11 @@ +@{ + RootModule = 'ITD.All-General.psm1' + ModuleVersion = '' + GUID = '9c9219d5-d7be-49e5-8448-49c50df94eda' + Author = 'Zack Meier' + CompanyName = 'State of North Dakota' + Description = "QoL functions that don't fit into another module" + PowerShellVersion = '5.1' + CompatiblePSEditions = 'Desktop', 'Core' + FunctionsToExport = @() +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psm1 b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/ITD.All-General.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Public/ConvertTo-Array.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Public/ConvertTo-Array.ps1 new file mode 100644 index 0000000..6157592 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Public/ConvertTo-Array.ps1 @@ -0,0 +1,32 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + $servers=@" + server1.xyz.com + servers2.xyz.com + @" + + $servers = ConvertTo-Array -MultiLineString $servers +.EXAMPLE + Another example of how to use this cmdlet +#> +function ConvertTo-Array { + [CmdletBinding()] + Param + ( + [string] + $MultiLineString + ) + + Begin { + } + Process { + $result = @($MultiLineString -split '[\r\n]+') + } + End { + return $result + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Public/Get-SslCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Public/Get-SslCertificate.ps1 new file mode 100644 index 0000000..80d235c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Public/Get-SslCertificate.ps1 @@ -0,0 +1,43 @@ +<# +.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-SslCertificate { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [string]$DNSName + ) + + process { + Write-Verbose "Checking certificate for $DNSName" + + $tcp = [Net.Sockets.TcpClient]::new($DNSName, 443) + $ssl = [Net.Security.SslStream]::new( + $tcp.GetStream(), + $false, + { $true } + ) + + $ssl.AuthenticateAsClient($DNSName) + + $cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new( + $ssl.RemoteCertificate + ) + + $ssl.Dispose() + $tcp.Dispose() + + $cert + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Public/Test-ADCredential.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Public/Test-ADCredential.ps1 new file mode 100644 index 0000000..2337636 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Public/Test-ADCredential.ps1 @@ -0,0 +1,49 @@ +<# +.Synopsis + Verify AD credentials are valid +.DESCRIPTION + Verify AD credentials are valid ## +.EXAMPLE + Test-ADCredential -Credential +#> +function Test-ADCredential { + [CmdletBinding()]# + Param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credential + ) + + Begin { + + } + Process { + If ($Credential -eq $null) { + Write-Warning "Credentials empty" + $status = $true + } + Else { + $username = $Credential.username + $password = $Credential.GetNetworkCredential().password + $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName + Add-Type -AssemblyName System.DirectoryServices.AccountManagement + $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('domain') + + #($ValidateCredential = ) | Out-Null + + If ($DS.ValidateCredentials($UserName, $Password) -eq $false) { + $password = $null + Write-Error "Invalid credentials or locked account." + $status = $false + } + Else { + $status = $true + } + + $password = $null + } + } + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Public/Uninstall-ITDModuleOldVersion.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Public/Uninstall-ITDModuleOldVersion.ps1 new file mode 100644 index 0000000..9e9a4c2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Public/Uninstall-ITDModuleOldVersion.ps1 @@ -0,0 +1,50 @@ +<# +.SYNOPSIS + Removes old versions of ITD modules +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Uninstall-ITDModuleOldVersion { + [CmdletBinding()] + Param + ( + ) + + begin { + } + + process { + $InstalledModules = Get-InstalledModule -Name ITD.* + + try { + $InstalledModules | ForEach-Object { + $CurrentVersion = $_.Version + Get-InstalledModule -Name $_.Name -AllVersions | Where-Object -Property Version -LT -Value $CurrentVersion + } | Uninstall-Module -Verbose + } + catch { + + } + + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/Public/Update-ITDModule.ps1 b/_NDGOV_WindowsTeam/ITD.All-General/Public/Update-ITDModule.ps1 new file mode 100644 index 0000000..44d4fbb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/Public/Update-ITDModule.ps1 @@ -0,0 +1,33 @@ +<# +.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-ITDModule { + [CmdletBinding()] + param ( + + ) + + begin { + + } + + process { + $InstalledModules = Get-InstalledModule -Name ITD.* + Update-Module -Name $InstalledModules.Name + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.All-General/README.md b/_NDGOV_WindowsTeam/ITD.All-General/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.All-General/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/azure-pipelines.yml new file mode 100644 index 0000000..5c618a0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.ITD-WindowsServer.FileManagement' + +variables: + major: 0 + minor: 7 + 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.ITD-WindowsServer.FileManagement.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.ITD-WindowsServer.FileManagement.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/build.ps1 new file mode 100644 index 0000000..b6b04d5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.ITD-WindowsServer.FileManagement' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.ITD-WindowsServer.FileManagement).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/^template.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/^template.json new file mode 100644 index 0000000..44d7df5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/^template.json @@ -0,0 +1,21 @@ +{ + "ComputerName": "itdxyz.nd.gov", + "NotifyEmail": [ + "emailA@nd.gov", + "emailB@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs\\LogFiles", + "Extension": "log", + "DaysToKeep": 90, + "Recursive": true + }, + { + "Path": "C:\\temp", + "Extension": "txt", + "DaysToKeep": 30, + "Recursive": false + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itddohslimst2.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itddohslimst2.nd.gov.json new file mode 100644 index 0000000..38e76df --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itddohslimst2.nd.gov.json @@ -0,0 +1,26 @@ +{ + "ComputerName": "itddohslimst2.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs", + "Extension": "log", + "DaysToKeep": 120, + "Recursive": true + }, + { + "Path": "C:\\Program Files\\STARLIMS\\STARLIMStst\\Log", + "Extension": "log", + "DaysToKeep": 120, + "Recursive": true + }, + { + "Path": "E:\\Program Files\\STARLIMS\\STARLIMSdev\\Log", + "Extension": "log", + "DaysToKeep": 120, + "Recursive": true + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappt01.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappt01.nd.gov.json new file mode 100644 index 0000000..a065701 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappt01.nd.gov.json @@ -0,0 +1,14 @@ +{ + "ComputerName": "itdernappt01.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs", + "Extension": "log", + "DaysToKeep": 90, + "Recursive": true + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappu01.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappu01.nd.gov.json new file mode 100644 index 0000000..16924b0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdernappu01.nd.gov.json @@ -0,0 +1,14 @@ +{ + "ComputerName": "itdernappu01.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs", + "Extension": "log", + "DaysToKeep": 90, + "Recursive": true + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdscmt1.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdscmt1.nd.gov.json new file mode 100644 index 0000000..d15429c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdscmt1.nd.gov.json @@ -0,0 +1,20 @@ +{ + "ComputerName": "itdscmt1.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs", + "Extension": "log", + "DaysToKeep": 90, + "Recursive": true + }, + { + "Path": "C:\\temp", + "Extension": "txt", + "DaysToKeep": 30, + "Recursive": false + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdvmvc1script.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdvmvc1script.nd.gov.json new file mode 100644 index 0000000..ac65335 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdvmvc1script.nd.gov.json @@ -0,0 +1,14 @@ +{ + "ComputerName": "itdvmvc1script.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\inetpub\\logs\\LogFiles", + "Extension": "log", + "DaysToKeep": 90, + "Recursive": true + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdwinautot1.nd.gov.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdwinautot1.nd.gov.json new file mode 100644 index 0000000..954820e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Helpers/itdwinautot1.nd.gov.json @@ -0,0 +1,14 @@ +{ + "ComputerName": "itdwinautot1.nd.gov", + "NotifyEmail": [ + "zmeier@nd.gov" + ], + "Directory": [ + { + "Path": "C:\\temp", + "Extension": "txt", + "DaysToKeep": 30, + "Recursive": false + } + ] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.nuspec b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.nuspec new file mode 100644 index 0000000..7bb5377 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.nuspec @@ -0,0 +1,12 @@ + + + + ITD.ITD-WindowsServer.FileManagement + $VERSIONHERE$ + Zack Meier + Functions for Windows Server file management + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psd1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psd1 new file mode 100644 index 0000000..af30450 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.ITD-WindowsServer.FileManagement' +# +# Generated by: zmeier +# +# Generated on: 6/14/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.ITD-WindowsServer.FileManagement.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + # ID used to uniquely identify this module + GUID = '85e7676b-f0e3-4908-aafa-25c9606ca8b7' + + # 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 Windows Server file management' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psm1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/ITD.ITD-WindowsServer.FileManagement.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.json b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.json new file mode 100644 index 0000000..b0aba7a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.json @@ -0,0 +1,26 @@ +[ + { + "ComputerName": "itdscmt1.nd.gov", + "NotifyEmail": "zmeier@nd.gov", + "Directory": [ + { + "Path": "C:\\inetpub\\logs\\LogFiles", + "DaysToKeep": 120, + "Extension": "log", + "Recursive": true + } + ] + }, + { + "ComputerName": "itdzmtest555.nd.gov", + "NotifyEmail": "zmeier@nd.gov", + "Directory": [ + { + "Path": "C:\\windows\\temp", + "DaysToKeep": 99, + "Extension": "log", + "Recursive": false + } + ] + } +] \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.yml b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.yml new file mode 100644 index 0000000..50bcd0e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFiles.yml @@ -0,0 +1,22 @@ +- ComputerName: itdscmt1.nd.gov + Directory: + - Path: C:\windows\temp + DaysToKeep: 30 + Extension: txt + Recursive: false +- ComputerName: itdsccmp2.nd.gov + Directory: + - Path: C:\windows\temp + DaysToKeep: 15 + Extension: txt + Recursive: false + - Path: C:\inetpub\logs + DaysToKeep: 120 + Extension: txt + Recursive: false +- ComputerName: itdzmtest555.nd.gov + Directory: + - Path: "C:\windows\temp", + DaysToKeep": 99, + Extension": "log", + Recursive": false diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFilesSource.jsonbak b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFilesSource.jsonbak new file mode 100644 index 0000000..3cb9c4a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Private/ITDExpiredFilesSource.jsonbak @@ -0,0 +1,14 @@ +[ + { + "Path": "C:\\temp", + "Extension": "log", + "DaysToKeep": 30, + "Recursive": true + }, + { + "Path": "C:\\temp2", + "Extension": "txt", + "DaysToKeep": 45, + "Recursive": false + } +] \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Get-ITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Get-ITDExpiredFiles.ps1 new file mode 100644 index 0000000..fcdb183 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Get-ITDExpiredFiles.ps1 @@ -0,0 +1,89 @@ +<# +.SYNOPSIS + Script will discover all files that are considered "expired". +.DESCRIPTION + Script will discover all files that are considered "expired" based on the parameters in the ./Helpers/ITDExpiredFiles.json files in the ITD-WindowsServer module +.NOTES + Information or caveats about the function e.g. 'This function is not supported in Linux' +.LINK + +.EXAMPLE + Get-ITDExpiredFiles +.EXAMPLE + Get-ITDExpiredFiles -Credential $PrvCred +.EXAMPLE + Get-ITDExpiredFiles -ComputerName itdxyz.nd.gov -Credential $PrvCred +#> + +function Get-ITDExpiredFiles { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [PSCredential] + $Credential + ) + Begin { + Write-Verbose -Message "Load json files into memory" + $JsonFiles = Get-ChildItem -Path "$PSScriptRoot\..\Helpers\*.json" | Where-Object Name -NE ^template.json + $MachineInfo = ForEach ($file in $JsonFiles) { + Get-Content -Path $file.FullName | ConvertFrom-Json + } + + If ($PSBoundParameters.ContainsKey('ComputerName')) { + Write-Verbose -Message "ComputerName found" + $MachineInfo = $MachineInfo | Where-Object ComputerName -EQ $ComputerName + } + } + + Process { + Write-Verbose -Message "Prep discovery function" + $GetExpiredFilesFunc = { + Write-Verbose -Message ($env:COMPUTERNAME + " " + $args[0] + " " + $args[1] + " " + $args[2]) + + $GetChildItemParams = @{ + Path = $args[0]; + Filter = $args[1]; + Recurse = $args[2]; + } + + $FilesFound = (Get-ChildItem @GetChildItemParams | Where-Object LastWriteTime -LT ((Get-Date).AddDays(-$args[3]))) + Write-Output $FilesFound + } + + $GetITDExpiredFilesResult = [System.Collections.ArrayList]@() + ForEach ($Server in $MachineInfo) { + Write-Verbose -Message ("Start " + $Server.ComputerName) + + Write-Verbose -Message "Ping test before any Invoke-Command" + If ((Test-NetConnection -ComputerName $Server.ComputerName).PingSucceeded) { + ForEach ($Directory in $Server.Directory) { + Write-Verbose -Message ("Start " + $server.ComputerName + " " + $Directory.Path) + $FilesFoundOnServer = $null + $InvokeCommandParams = $null + $InvokeResult = $null + + $InvokeCommandParams = @{ + ComputerName = $Server.ComputerName; + Credential = $Credential; + ScriptBlock = $GetExpiredFilesFunc; + ArgumentList = @($Directory.Path, ("*" + $Directory.Extension), $Directory.Recursive, $Directory.DaysToKeep); + } + $FilesFoundOnServer = Invoke-Command @InvokeCommandParams + Write-Output $FilesFoundOnServer + #$null = $GetITDExpiredFilesResult.Add($FilesFoundOnServer) + Write-Verbose -Message ("End " + $server.ComputerName + " " + $Directory.Path) + } + } + Else { + Write-Error -Message ($Server.ComputerName + " ping test failed, generate ticket someday.") + } + } + Write-Verbose -Message ("End " + $server.ComputerName) + } + End { + #Write-Output $GetITDExpiredFilesResult + Write-Verbose -Message "End Get-ITDExpiredFiles" + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Remove-ITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Remove-ITDExpiredFiles.ps1 new file mode 100644 index 0000000..2cfb7b9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/Public/Remove-ITDExpiredFiles.ps1 @@ -0,0 +1,99 @@ +function Remove-ITDExpiredFiles { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [switch] + $WhatIf, + + [PSCredential] + $Credential + ) + Begin { + Write-Verbose -Message "Start Remove-ITDExpiredFiles" + } + Process { + $FilesRemovedSuccess = @() + $FilesRemovedFailure = @() + $GetITDExpiredFilesAutoParams += @{} + + If ($PSBoundParameters.ContainsKey('ComputerName')) { + Write-Verbose -Message "ComputerName parameter found" + $GetITDExpiredFilesParams += @{ + ComputerName = $ComputerName; + } + } + + If ($PSBoundParameters.ContainsKey('Credential')) { + Write-Verbose -Message "Credential parameter found" + $GetITDExpiredFilesParams += @{ + Credential = $Credential; + } + } + $FilesToRemove = Get-ITDExpiredFiles @GetITDExpiredFilesParams + Write-Verbose -Message ("Found " + $FilesToRemove.count + " expired files to remove") + + ForEach ($File in $FilesToRemove) { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName ) + $InvokeCommandParams = @{ + ComputerName = $File.PSComputerName; + Credential = $Credential; + ErrorAction = 'Stop'; + ArgumentList = @($File.FullName); + ScriptBlock = { Get-Item -Path $args[0] | Remove-Item } + } + + switch ($WhatIf) { + $true { + try { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + Write-Host -Message ($Server.ComputerName + " -- " + 'What if: Performing the operation "Remove File" on target ' + $File.FullName) + # log success + $FilesRemovedSuccess += [PSCustomObject]@{ + ComputerName = $File.PSComputerName; + Name = $File.Fullname; + Timestamp = (Get-Date).tostring("yyyy/MM/dd HH:mm:ss") + } + Write-Output $File + } + catch { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure + $FilesRemovedFailure += [PSCustomObject]@{ + ComputerName = $File.PSComputerName; + Name = $File.Fullname; + Timestamp = (Get-Date).tostring("yyyy/MM/dd HH:mm:ss") + } + } + } + Default { + try { + Invoke-Command @InvokeCommandParams + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + # log success + $FilesRemovedSuccess += [PSCustomObject]@{ + ComputerName = $File.PSComputerName; + Name = $File.Fullname; + Timestamp = (Get-Date).tostring("yyyy/MM/dd HH:mm:ss") + } + Write-Output $File + } + catch { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure + $FilesRemovedFailure += [PSCustomObject]@{ + ComputerName = $File.PSComputerName; + Name = $File.Fullname; + Timestamp = (Get-Date).tostring("yyyy/MM/dd HH:mm:ss") + } + } + } + } + Write-Verbose -Message ("End~" + $File.PSComputerName + "~" + $File.FullName ) + } + } + End { + Write-Verbose -Message "End Remove-ITDExpiredFilesAuto" + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/README.md b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.FileManagement/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/azure-pipelines.yml new file mode 100644 index 0000000..a0974a0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.ITD-WindowsServer.General' + +variables: + major: 0 + minor: 7 + 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.ITD-WindowsServer.General.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.ITD-WindowsServer.General.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/build.ps1 new file mode 100644 index 0000000..814d678 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.ITD-WindowsServer.General' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.ITD-WindowsServer.General).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVm.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVm.ps1 new file mode 100644 index 0000000..874d5a1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVm.ps1 @@ -0,0 +1,93 @@ +<# +.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-ITDWindowsVM { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [ValidateSet('VMware', 'Azure')] + [string] + $Platform, + + [Parameter(Mandatory = $true)] + [string] + $ComputerName, + + [Parameter(Mandatory = $true)] + [int] + $CPU, + + [Parameter(Mandatory = $true)] + [int] + $MemoryGB, + + [Parameter(Mandatory = $true)] + [int] + $DiskOS, + + [Parameter(Mandatory = $true)] + [int] + $DiskSwap, + + [int] + $DiskData = 0, + + [Parameter(Mandatory = $true)] # this will decide Azure subscription + [string] + $Subnet, + + [Parameter(Mandatory = $true)] + [string] + $OS, + + [Parameter(Mandatory = $true)] + [string] + $Environment, + + [Parameter(Mandatory = $true)] + [string] + $Datacenter, + + [Parameter(Mandatory = $true)] + [string] + $AppName, + + [Parameter(Mandatory = $true)] + [string] + $LicensingRestrictions, + + [Parameter(Mandatory = $true)] + [PSCredential] + $Credential + ) + + begin { + + } + + process { + switch ($Platform) { + 'VMware' { + # New-ITDWindowsVmVmware + } + 'Azure' { + # New-ITDWindowsVmAzure + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmAzure.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmAzure.ps1 new file mode 100644 index 0000000..5acbe1c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmAzure.ps1 @@ -0,0 +1,694 @@ +<# ################ +.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 + $NewVMWindowsAzureParams = @{ + ComputerName = 'itdzmtest701.nd.gov'; + ResourceGroupNameOverride = 'rg-shared-iis-tst'; + AvailabilityZone = 2; + CPU = 2; + MemoryGB = 16; + DiskOsGB = 128; + DiskDataGB = 0; + Subnet = '10.21.8.0/22'; + OS = 'Windows Server 2022 Datacenter'; + Environment = 'Test'; + AppName = 'ITD-POC-zmeier'; + LicensingRestrictions = "No Licensing Restrictions"; + } + + New-ITDWindowsVmAzure @NewVMWindowsAzureParams -Credential $PrvCred -Verbose +#> + +function New-ITDWindowsVmAzure { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [string] + $ResourceGroupNameOverride, + + [string] + $AppName, + + [ValidateSet(1, 2, 3)] + [int] + $AvailabilityZone, + + [int] + $CPU, + + [int] + $MemoryGB, + + [int] + $DiskOsGB, + + [int] + $DiskDataGB, + + [string] + $Subnet, + + [string] + $OS, + + [string] + $Environment, + + #[string] + #$Subscription, + + [string] + $LicensingRestrictions, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + $ComputerName = $ComputerName.ToLower() + $FQDN = $ComputerName + $Hostname = $FQDN.split('.')[0] + + Write-Verbose -Message "Prepare Connections" + #$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' + #$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' + #$SecureStringPwd = '' #$Secret:AzureVMServicePrincipal #Pqt8Q~E-dDmQugcPPWdaK2t_4retS41VVVVOZbOx + #$SecureStringPwd = 'Pqt8Q~E-dDmQugcPPWdaK2t_4retS41VVVVOZbOx' + #$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) + #Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + + Write-Verbose -Message "Prepare Credentials" + $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password)) + + Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one" + Clear-DnsClientCache + $Cidr = $Subnet + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -Server 10.10.10.10 -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($null -ne $IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record." + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + Write-Verbose -Message ("FQDN is " + $FQDN) + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + #[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress + + [Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it." + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential -ErrorAction SilentlyContinue + If ($GuestVMLocalCredential) { + Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials" + } + Else { + Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials" + $GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential + } + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + + Write-Verbose -Message "Determine environment" + switch ($Environment) { + { $_ -eq 'Test' -or $_ -eq 'Development' } { + Write-Verbose -Message "Environment is Test or Development" + $EnvShortString = 'tst' + } + 'Production' { + Write-Verbose -Message "Environment is Production" + $EnvShortString = 'prd' + } + } + + Write-Verbose -Message "Determine subscription, via Subnet" + $AllSubscriptions = Get-AzSubscription + $AllAzVirtualNetworks = ForEach ($Subscription in $AllSubscriptions) { + Set-AzContext -SubscriptionObject $Subscription | Out-Null + Get-AzVirtualNetwork | ForEach-Object { + [PSCustomObject]@{ + Subscription = $Subscription.Name; + VirtualNetwork = $_ + } + } + } + + $Subscription = ($AllAzVirtualNetworks | Where-Object { $_.VirtualNetwork.Subnets.AddressPrefix -match $Subnet }).Subscription + $VirtualNetwork = ($AllAzVirtualNetworks | Where-Object { $_.VirtualNetwork.Subnets.AddressPrefix -match $Subnet }).VirtualNetwork + $VirtualNetworkSubnet = $VirtualNetwork.Subnets | Where-Object { $_.AddressPrefix -match $Subnet } + + $VNetName = $VirtualNetwork.Name + $VNetSubnet = $VirtualNetworkSubnet.Name + + switch ($OS) { + "Windows Server 2019 Datacenter" { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2019-Datacenter" + } + "Windows Server 2022 Datacenter" { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2022-datacenter" + } + Default { Write-Error "Invalid operating system" -ErrorAction Stop } + } + + # finalize VM location and size + $location = "centralus" + $VMSizeFilter1 = @( + "Standard_D2ds_v5", + "Standard_D4ds_v5", + "Standard_D8ds_v5", + "Standard_D16ds_v5", + "Standard_D32ds_v5", + "Standard_E2ds_v5", + "Standard_E4ds_v5", + "Standard_E8ds_v5", + "Standard_E16ds_v5", + "Standard_E20ds_v5", + "Standard_E32ds_v5", + "Standard_F2s_v2", + "Standard_F4s_v2", + "Standard_F8s_v2", + "Standard_F16s_v2", + "Standard_F32s_v2" + ) + + $VMSize = Get-AzVMSize -Location centralus | ` + Where-Object { $VMSizeFilter1 -contains $_.Name } | ` + Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | ` + Where-Object Name -NotMatch "_Promo" | ` + Sort-Object NumberOfCores, MemoryInMB | ` + Select-Object -First 1 + + Write-Verbose -Message "Determine ResourceGroupName, and create Resource Group if needed" + If ($PSBoundParameters.ContainsKey('ResourceGroupNameOverride')) { + # use the name in the variable + Write-Verbose -Message "ResourceGroupName parameter found, is $ResourceGroupNameOverride" + $ResourceGroupName = $ResourceGroupNameOverride + } + Else { + Write-Verbose -Message "ResourceGroupName parameter not found, determine now" + # if name is not given, determine the name + $VMOwner = $AppName.split('-')[0].ToLower() + $VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " " + $ResourceGroupName = "rg-$VMOwner-$VMFunction-$EnvShortString" + } + Write-Verbose -Message "ResourceGroupName is $ResourceGroupName" + + Write-Verbose -Message "Change to selected subscription and validate resource group exists" + Set-AzContext $Subscription | Out-Null + $ResGroupExist = $null + $ResGroupExist = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue + + If (@($ResGroupExist).count -gt 1) { + Write-Error "Multiple Resource Groups matched" -ErrorAction Stop + } + If (@($ResGroupExist).count -lt 1) { + Write-Warning "No matching resource group found, creating it now" + New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Tag @{ApplicationName = $AppName } + } + If (@($ResGroupExist).count -eq 1) { + Write-Verbose -Message "Exactly one matching resource group found" + } + + $VMName = "vm-$HostName-$EnvShortString" + $VMIPConfigName = "ipconfig-$HostName-$EnvShortString" + $VMNicName = "nic-$HostName-$EnvShortString" + $VMObjectName = "vm-$HostName-$EnvShortString" + $VMOsDiskName = "vm-$HostName-os-$EnvShortString" + + Write-Verbose -Message "Verifying Applicable Inputs are Lowercase" + $VMIPConfigName = $VMIPConfigName.ToLower() + $VMNicName = $VMNicName.ToLower() + $VMObjectName = $VMObjectName.ToLower() + $VMOsDiskName = $VMOSDiskName.ToLower() + + Write-Verbose -Message "Creating IPConfig and NIC" + $IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $IPAddress.IPAddressToString -PrivateIpAddressVersion IPv4 -Subnet $VirtualNetworkSubnet + $VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $Location -Name $VMNICName -ResourceGroupName $ResourceGroupName -Subnet $VirtualNetworkSubnet -Force + $VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static" + $VMNIC.IpConfigurations[0].PrivateIpAddress = $IPAddress.IPAddressToString + Set-AzNetworkInterface -NetworkInterface $VMNIC + + Write-Verbose -Message "Build VM Config" + $vmConfigParams = @{ + VMName = $VMObjectName + VMSize = $VMSize.Name + } + + If ($PSBoundParameters.ContainsKey('AvailabilityZone')) { + Write-Verbose -Message "AvailabilityZone parameter found, adding to vmConfigParams" + $vmConfigParams += @{ + Zone = $AvailabilityZone + } + } + + $vmConfig = New-AzVMConfig @vmConfigParams + $vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage + If ($VMOS -eq "Windows") { + $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $GuestVMLocalCredential + $vmConfig | Set-AzVMSourceImage -PublisherName $Publisher -Offer $Offer -Skus $Sku -Version latest + $vmConfig.OSProfile.ComputerName = $HostName + } + If ($VMOS -eq "Linux") { + $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $GuestVMLocalCredential + Switch ($VMSubscription) { + "npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" } + "infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" } + "prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" } + } + } + + $vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID + Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroupName + + Write-Verbose "Creating VM" + New-AzVM -VM $vmConfig -ResourceGroupName $ResourceGroupName -Location $Location -DisableBginfoExtension -LicenseType "Windows_Server" #-AsJob + + Start-Sleep -Seconds 60 + + $VM = Get-AzVM -Name $VMObjectName -ResourceGroupName $ResourceGroupName + + If ($PSBoundParameters.ContainsKey("DiskDataGB")) { + $ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$environment-") } }) + + $NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1 + $NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000") + $NewDiskName = "vm-$Hostname-app-$EnvShortString-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001 + + $LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1 + + $count = 0 + + If ($ExistingDisks) { + while ($Size -match $ExistingDisks.DiskSizeGB) { + $count++ + Write-Verbose -Message "SizeGB: $Size, Count: $count" + If ($count -ge 11) { + Write-Error "Disk size not available" -ErrorAction Stop + } + Else { + $Size = $Size - 1 + } + } + } + + Write-Verbose -Message "SizeGB: $Size, Count: $count" + + $AzureRmDiskConfigParams = @{ + DiskSizeGB = $DiskDataGB + Location = $Location + CreateOption = "Empty" + SkuName = "Premium_LRS" + } + + If ($Zone) { + Write-Verbose "VM is located in Zone $Zone" + $AzureRmDiskConfigParams += @{Zone = $Zone } + } + #$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS + $DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams + + If (!(Get-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $NewDiskName -ErrorAction SilentlyContinue)) { + $NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroupName + + $VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -AsJob + } + } + + Write-Verbose -Message "Wait two minutes before Pre-Firewall Guest OS customization" + Start-Sleep -Seconds 120 + + Write-Verbose -Message "Begin Pre-Firewall Guest OS customization" + $InvokeAzVMRunCommandParams = @{ + ResourceGroupName = $ResourceGroupName; + Name = $VMName; + CommandId = 'RunPowerShellScript' + } + + Write-Verbose -Message "1-Set WMI Tags" + $ScriptBlock = { + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "3-Disk Configuration" + $ScriptBlock = { + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "5-Time Zone" + $ScriptBlock = { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "6-Enable Performance Counters" + $ScriptBlock = { + # Enable Performance Counters + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "7-Disable Windows Firewall" + $ScriptBlock = { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + # determine Active Directory Forest and OU + Write-Verbose -Message "8a-Determine domain join" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? + $ScriptBlock = { + Param( + [string] + $DomainName, + + [string] + $OuPath + ) + + Write-Host $OuPath + Test-NetConnection -ComputerName nd.gov + + $DomainJoinCred = New-Object System.Management.Automation.PSCredential('ndgov\svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) + Add-Computer -DomainName $DomainName -OUPath $OuPath -Credential $DomainJoinCred + + Restart-Computer -Force + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock -Parameter @{ + "DomainName" = 'nd.gov'; + "OuPath" = "$OuFinal" + } + } + } + + Start-Sleep -Seconds 120 + + Write-Verbose -Message "10a-Copy SCCM client from itdsccmp2.nd.gov" -Verbose + $ScriptBlock = { #### NEEDS WORK + Param( + + ) + + Copy-Item -path "\\itdsccmp2.nd.gov\SCCM_Client\Client\" -Destination C:\temp\SCCM_Client -Recurse + } + + $CopySuccess = $false + $CopyAttempts = 0 + While ($CopySuccess -eq $false -and $CopyAttempts -lt 100) { + $Attempts++ + $InvokeResult = Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + If ($InvokeResult.value.message -like "Copy-Item : Cannot find path*") { + Write-Verbose -Message "SCCM Client file copy failed. Looping until it works." -Verbose + $CopySuccess = $false + } + Else { + Write-Verbose -Message "SCCM Client file copy success." -Verbose + $CopySuccess = $true + } + } + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString { + Get-Content C:\Windows\CCM\Logs\ClientIDManagerStartup.log | Select-String RegTask + } + If ($CcmRegistration.value.message -match "Client is registered") { + Write-Verbose "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.value.message -match "Client is already registered") { + Write-Verbose "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Verbose -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $Credential -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmVMware.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmVMware.ps1 new file mode 100644 index 0000000..dc6d856 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Helpers/old_needs_review/New-ITDWindowsVmVMware.ps1 @@ -0,0 +1,1037 @@ +<# +.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 + $NewITDWindowsVmVMwareParams = @{ + ComputerName = 'itdzmtest300.nd.gov'; + CPU = 2; + MemoryGB = 8; + DiskOsGB = 50; + DiskSwapGB = 9; + DiskDataGB = 20; + Subnet = '10.11.12.0/23'; + OS = 'Windows Server 2022 Datacenter'; + Environment = "Test"; + Datacenter = "Bismarck"; + AppName = "ITD-POC-zmeier"; + StartupPriority = 4; + LicensingRestrictions = "No Licensing Restrictions"; + Credential = $PrvCred; + } + + New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams +#> + +function New-ITDWindowsVmVMware { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [int] + $CPU, + + [int] + $MemoryGB, + + [int] + $DiskOsGB, + + [int] + $DiskSwapGB, + + [int] + $DiskDataGB, + + [string] + $Subnet, + + [string] + $OS, + + [string] + $Environment, + + [string] + $Datacenter, + + [string] + $AppName, + + [int] + $StartupPriority, + + [string] + $LicensingRestrictions, + + [PSCredential] + $Credential + + ) + + begin { + + } + + process { + $ComputerName = $ComputerName.ToLower() + $FQDN = $ComputerName + $HostName = $FQDN.split('.')[0] + + If ($Environment -eq "Development") { + $Environment = "Test" + } + + Write-Verbose -Message "Prepare Credentials and Connections" + $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password)) + + Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one" + Write-Verbose -Message "ComputerName: $ComputerName" -Verbose + Write-Verbose -Message "FQDN: $FQDN" -Verbose + Write-Verbose -Message "Hostname: $Hostname" -Verbose + + Clear-DnsClientCache + $InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred + $Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue -Server 10.10.10.10).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($null -ne $IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose -Message "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, but does not match CIDR Block" + Break + } + } + Else { + Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record." + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + Write-Verbose -Message ("FQDN is " + $FQDN) + ####### + ####### Review this code after DNS problems resolved - 2024/09/24 zm + ####### + ####### [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress + + [Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it." + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential -ErrorAction SilentlyContinue + If ($GuestVMLocalCredential) { + Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials" + } + Else { + Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials" + $GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential + } + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + + Write-Verbose -Message "Decide VMware Cluster and Licensing" + switch ($LicensingRestrictions) { + "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Enterprise" { $ClusterRoot = "SQLe" } + "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "SQLa" } + "IBM Websphere" { $ClusterRoot = "WAS" } + "Powerschool" { $ClusterRoot = "PS" } + "Pexip" { $ClusterRoot = "TEL" } + } + + Write-Verbose -Message "Decide Datacenter" + switch ($Datacenter) { + "Bismarck" { $ClusterInt = 1 } + "Mandan" { $ClusterInt = 2 } + } + + $Cluster = $ClusterRoot + $ClusterInt + Write-Verbose -Message "VMware Cluster is $Cluster, gathering metadata for $Cluster" + + switch ($Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "SQLa1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQLa1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLa1_FS92_Gen" + } + "SQLa2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQLa2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLa2_FS92_Gen" + } + "SQLe1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQLe1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLe1_FS92_Gen" + } + "SQLe2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQLe2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLe2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + } + + Write-Verbose -Message "Validate entered disk sizes" + Write-Verbose -Message "DiskOsGB is $DiskOsGB. Validating its not a stupid number." -Verbose + switch ($DiskOsGB) { + { $_ -lt 50 } { + Write-Verbose -Message "DiskOsGB is 0 or below. Since an OS Disk is required, defaulting to 50GB" -Verbose + $DiskOsGB = 50 + } + } + + Write-Verbose -Message "DiskSwapGB is $DiskSwapGB. Validating its not a stupid number." -Verbose + switch ($DiskSwapGB) { + { $_ -le 0 } { + Write-Verbose -Message "DiskSwapGB is zero or below. Since an Swap Disk is required, defaulting to `$Memory + 1GB." -Verbose + $DiskSwapGB = ($MemoryGB + 1) + } + } + + Write-Verbose -Message "DiskDataGB is $DiskDataGB. Validating its not a stupid number." -Verbose + switch ($DiskDataGB) { + { $_ -le 0 } { + Write-Verbose -Message "DiskDataGB is 0. Since an Data Disk is optional, data disk will not be created." -Verbose + $DiskDataGB = 0 + } + { $_ -gt 500 } { + Write-Verbose -Message "DiskDataGB is 500GB or more. DiskDataGB will be set to the maximum of 500GB." -Verbose + $DiskDataGB = 500 + } + } + + Write-Verbose -Message "Determine Datastore / Datastore Cluster" + $DiskTotal = $DiskOsGB + $DiskSwapGB + $DiskDataGB + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + Write-Verbose -Message "Determine VMware VM Template for OS: $OS" + switch ($OS) { + "Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard 1809.19" } + "Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Standard 1809.19" } + "Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Standard 2108.21" } + Default { Write-Error "Invalid template" -ErrorAction Stop } + } + + Write-Verbose -Message "Determine VMware Port Group" + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_*" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt) + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + Write-Verbose -Message "Configure Guest OS Customization Spec" + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + + Get-OSCustomizationSpec -Name 'Windows (Auto)' -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + + Set-Location C:\Temp + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $ComputeCluster.Name; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec + } + try { + New-VM @NewVMParams + } + catch { + Write-Error $Error[0] + Exit + } + + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } ## takes a long time to execute + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + Write-Verbose -Message "Config and Update Disks" + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + Write-Verbose -Message "Update Disk 1" + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $DiskOsGB) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $DiskOsGB -Confirm:$false + } + + Write-Verbose -Message "Config Disk 2" + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB ($MemoryGB + 1) ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $DiskSwapGB) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $DiskSwap -Confirm:$false + } + + Write-Verbose -Message "Config Disk 3" + If ($DiskDataGB -gt 0) { + Write-Verbose -Message "$DiskDataGB greater than zero" + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $DiskDataGB ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $DiskDataGB) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $DiskData -Confirm:$false + } + } + + Write-Verbose -Message "Set vCenter Tags on VM" + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category AppName -Name $AppName) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category DTAP -Name $Environment) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category LicensingRestrictions -Name $LicensingRestrictions) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category StartupPriority -Name $StartupPriority) -Server $VIServer + # OS + + Write-Verbose -Message "Begin Post-Sysprep OS Guest Customization" + Write-Verbose -Message "Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking for DVD drive, and moving it to Z:\" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + Write-Host "hello1" + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking for unpartitioned space on C: volume and expanding" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + Write-Host "hello1" + # Expand C: Partition To Maximum Extent + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $Disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + If ($Disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + ForEach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + Else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." -Verbose + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." -Verbose + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." -Verbose + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." -Verbose + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." -Verbose + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Verbose -Message "Enabling Remote Management" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." -Verbose + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." -Verbose + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking current power plan, set to High Performance" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." -Verbose + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." -Verbose + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." -Verbose + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." -Verbose + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." -Verbose + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." -Verbose + } + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Verbose -Message "Enable the server manager performance monitors" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." -Verbose + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." -Verbose + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." -Verbose + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." -Verbose + } + } + + # Active Directory + Write-Verbose "Join Active Directory" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred -Server itddc12.nd.gov' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + else { + $GuestCredentialAB = $GuestCredentialBB + } + + Write-Verbose -Message ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) + + Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + Write-Verbose -Message ("[$FQDN]:SCCM client copy complete " + (Get-Date)) + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Verbose -Message "[$FQDN]:Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Verbose -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $Credential -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + + Write-Verbose -Message "Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Verbose -Message "Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + #Start-Sleep -Seconds 180 + + Write-Verbose -Message "Waiting for network connectivity / Then KVM Activation..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + + Write-Verbose -Message ("[$FQDN]:Add to Solarwinds") + $Func = { + param($C) + Import-SWDiscovery -ComputerName $C -Integration ServiceNow + } + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $FQDN -Credential $Credential + } + Write-Verbose -Message "[$FQDN]:End" + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.nuspec b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.nuspec new file mode 100644 index 0000000..da7652a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.nuspec @@ -0,0 +1,12 @@ + + + + ITD.ITD-WindowsServer.General + $VERSIONHERE$ + Zack Meier + Functions for Windows Server General administration + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psd1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psd1 new file mode 100644 index 0000000..22cdd15 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.ITD-WindowsServer.General' +# +# Generated by: zmeier +# +# Generated on: 6/14/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.ITD-WindowsServer.General.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + # ID used to uniquely identify this module + GUID = '3bb063c4-d6c3-4775-8f25-4bdf31fe4b05' + + # 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 Windows Server general administration' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psm1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/ITD.ITD-WindowsServer.General.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Private/New-ITDSSLCertificateSigningRequest.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Private/New-ITDSSLCertificateSigningRequest.ps1 new file mode 100644 index 0000000..98e440b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Private/New-ITDSSLCertificateSigningRequest.ps1 @@ -0,0 +1,154 @@ +<# +.SYNOPSIS + Generates a Certificate Signing Request based on values inputted. Any values not inputted will result in the use of default values. +.DESCRIPTION + Generates a Certificate Signing Request based on values inputted. Any values not inputted will result in the use of default values. CSR will be printed to the screen, but can be saved to the clipboard, or to a file. + Default values are: + +.NOTES + Run as administrator is required. +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' + CSR is generated using the common name shown, and default values for everything else +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -Organization "OrgNameHere" -OrganizationalUnit "OrgUnitHere" -Locality Mandan -State ND -Country US -KeyLength 4096 + CSR is generated using the values specified, defaults for the rest +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -Organization "OrgNameHere" -OrganizationalUnit "OrgUnitHere" -Locality Mandan -State ND -Country US -KeyLength 4096 -ToClipboard + CSR is generated using the values specified, defaults for the rest, and saved into the user's clipboard +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -ToPath C:\temp.csr + CSR is generated using the common name shown, and default values for everything else, and saves the CSR to a local path +#> + +function New-ITDSslCertificateSigningRequest { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string] + $CommonName, + + [string] + $Organization = "State of North Dakota", + + [string] + $OrganizationalUnit = "NDIT", + + [string] + $Locality = "Bismarck", + + [string] + $State = "ND", + + [string] + $Country = "US", + + [ValidateSet(2048, 4096)] + [int] + $KeyLength = 4096, + + [switch] + $Exportable = $true, + + [ValidateSet('sha256','sha384','sha512','md5')] + [string] + $HashAlgorithm = "sha256", + + [switch] + $ToClipboard, + + [string] + $ToPath + ) + + begin { + if (-NOT([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Write-Host "Administrator priviliges are required. Please restart this script with elevated rights." -ForegroundColor Red + Pause + Throw "Administrator priviliges are required. Please restart this script with elevated rights." + } + } + + process { + $UID = [guid]::NewGuid() + $files = @{} + $files['settings'] = "$($env:TEMP)\$($UID)-settings.inf"; + $files['csr'] = "$($env:TEMP)\$($UID)-csr.req" + + $request = @{} + $request['SAN'] = @{} + + #2048, sha256 + $settingsInf = " +[Version] +Signature=`"`$Windows NT`$ +[NewRequest] +KeyLength = {{KeyLength}} +Exportable = {{Exportable}} +MachineKeySet = TRUE +SMIME = FALSE +RequestType = PKCS10 +ProviderName = `"Microsoft RSA SChannel Cryptographic Provider`" +ProviderType = 12 +HashAlgorithm = {{HashAlgorithm}} +;Variables +Subject = `"CN={{CN}},OU={{OU}},O={{O}},L={{L}},S={{S}},C={{C}}`" +[Extensions] +{{SAN}} +;Certreq info +;http://technet.microsoft.com/en-us/library/dn296456.aspx +;CSR Decoder +;https://certlogik.com/decoder/ +;https://ssltools.websecurity.symantec.com/checker/views/csrCheck.jsp +" + + + $request['SAN_string'] = & { + if ($request['SAN'].Count -gt 0) { + $san = "2.5.29.17 = `"{text}`" +" + Foreach ($sanItem In $request['SAN'].Values) { + $san += "_continue_ = `"dns=" + $sanItem + "&`" +" + } + return $san + } + } + + $settingsInf = $settingsInf.Replace("{{CN}}", $CommonName) + $settingsInf = $settingsInf.Replace("{{O}}", $Organization) + $settingsInf = $settingsInf.Replace("{{OU}}", $OrganizationalUnit) + $settingsInf = $settingsInf.Replace("{{L}}", $Locality) + $settingsInf = $settingsInf.Replace("{{S}}", $State) + $settingsInf = $settingsInf.Replace("{{C}}", $Country) + $settingsInf = $settingsInf.Replace("{{SAN}}", $request['SAN_string']) + $settingsInf = $settingsInf.Replace("{{KeyLength}}",$KeyLength) + $settingsInf = $settingsInf.Replace("{{HashAlgorithm}}",$HashAlgorithm) + $settingsInf = $settingsInf.Replace("{{Exportable}}",$Exportable) + + # Save settings to file in temp + $settingsInf > $files['settings'] + + certreq -new $files['settings'] $files['csr'] > $null + + $CSR = Get-Content $files['csr'] + + Write-Output $CSR + If ($ToClipboard) { + $CSR | Set-Clipboard + } + If ($ToPath) { + $CSR | Out-File -FilePath $ToPath + } + + $files.Values | ForEach-Object { + Remove-Item $_ -ErrorAction SilentlyContinue + } + + + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/New-ITDSSLCertificateSigningRequest.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/New-ITDSSLCertificateSigningRequest.ps1 new file mode 100644 index 0000000..9bd1a09 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/New-ITDSSLCertificateSigningRequest.ps1 @@ -0,0 +1,154 @@ +<# +.SYNOPSIS + Generates a Certificate Signing Request based on values inputted. Any values not inputted will result in the use of default values. +.DESCRIPTION + Generates a Certificate Signing Request based on values inputted. Any values not inputted will result in the use of default values. CSR will be printed to the screen, but can be saved to the clipboard, or to a file. + Default values are: + +.NOTES + Run as administrator is required. +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' + CSR is generated using the common name shown, and default values for everything else +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -Organization "OrgNameHere" -OrganizationalUnit "OrgUnitHere" -Locality Mandan -State ND -Country US -KeyLength 4096 + CSR is generated using the values specified, defaults for the rest +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -Organization "OrgNameHere" -OrganizationalUnit "OrgUnitHere" -Locality Mandan -State ND -Country US -KeyLength 4096 -ToClipboard + CSR is generated using the values specified, defaults for the rest, and saved into the user's clipboard +.EXAMPLE + New-ITDSslCertificateSigningRequest -CommonName 'commonname.nd.gov' -ToPath C:\temp.csr + CSR is generated using the common name shown, and default values for everything else, and saves the CSR to a local path +#> + +function New-ITDSslCertificateSigningRequest { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string] + $CommonName, + + [string] + $Organization = "State of North Dakota", + + [string] + $OrganizationalUnit = "NDIT", + + [string] + $Locality = "Bismarck", + + [string] + $State = "ND", + + [string] + $Country = "US", + + [ValidateSet(2048, 4096)] + [int] + $KeyLength = 4096, + + [switch] + $Exportable = $true, + + [ValidateSet('sha256','sha384','sha512','md5')] + [string] + $HashAlgorithm = "sha256", + + [switch] + $ToClipboard, + + [string] + $ToPath + ) + + begin { + if (-NOT([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Write-Host "Administrator priviliges are required. Please restart this script with elevated rights." -ForegroundColor Red + Pause + Throw "Administrator priviliges are required. Please restart this script with elevated rights." + } + } + + process { + $UID = [guid]::NewGuid() + $files = @{} + $files['settings'] = "$($env:TEMP)\$($UID)-settings.inf"; + $files['csr'] = "$($env:TEMP)\$($UID)-csr.req" + + $request = @{} + $request['SAN'] = @{} + + #2048, sha256 + $settingsInf = " +[Version] +Signature=`"`$Windows NT`$ +[NewRequest] +KeyLength = {{KeyLength}} +Exportable = {{Exportable}} +MachineKeySet = TRUE +SMIME = FALSE +RequestType = PKCS10 +ProviderName = `"Microsoft RSA SChannel Cryptographic Provider`" +ProviderType = 12 +HashAlgorithm = {{HashAlgorithm}} +;Variables +Subject = `"CN={{CN}},OU={{OU}},O={{O}},L={{L}},S={{S}},C={{C}}`" +[Extensions] +{{SAN}} +;Certreq info +;http://technet.microsoft.com/en-us/library/dn296456.aspx +;CSR Decoder +;https://certlogik.com/decoder/ +;https://ssltools.websecurity.symantec.com/checker/views/csrCheck.jsp +" + + + $request['SAN_string'] = & { + if ($request['SAN'].Count -gt 0) { + $san = "2.5.29.17 = `"{text}`" +" + Foreach ($sanItem In $request['SAN'].Values) { + $san += "_continue_ = `"dns=" + $sanItem + "&`" +" + } + return $san + } + } + + $settingsInf = $settingsInf.Replace("{{CN}}", $CommonName) + $settingsInf = $settingsInf.Replace("{{O}}", $Organization) + $settingsInf = $settingsInf.Replace("{{OU}}", $OrganizationalUnit) + $settingsInf = $settingsInf.Replace("{{L}}", $Locality) + $settingsInf = $settingsInf.Replace("{{S}}", $State) + $settingsInf = $settingsInf.Replace("{{C}}", $Country) + $settingsInf = $settingsInf.Replace("{{SAN}}", $request['SAN_string']) + $settingsInf = $settingsInf.Replace("{{KeyLength}}",$KeyLength) + $settingsInf = $settingsInf.Replace("{{HashAlgorithm}}",$HashAlgorithm) + $settingsInf = $settingsInf.Replace("{{Exportable}}",$Exportable) + + # Save settings to file in temp + $settingsInf > $files['settings'] + + certreq -new $files['settings'] $files['csr'] > $null + + $CSR = Get-Content $files['csr'] + + Write-Output $CSR + If ($ToClipboard) { + $CSR | Set-Clipboard + } + If ($ToPath) { + $CSR | Out-File -FilePath $ToPath + } + + $files.Values | ForEach-Object { + Remove-Item $_ -ErrorAction SilentlyContinue + } + + New-ITDAutomationRecord -AppName "Windows-General" -Action "Provisioning" -Minutes 3 -Platform "PowerShell-ITD.Windows" + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/Remove-ITDSolarwindsNode.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/Remove-ITDSolarwindsNode.ps1 new file mode 100644 index 0000000..b9ddb2e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Public/Remove-ITDSolarwindsNode.ps1 @@ -0,0 +1,34 @@ +function Remove-ITDSolarwindsNode { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [PSCredential] + $Credential + ) + + begin { + } + + process { + + $Func = { + Import-Module -Name ITDSolarwinds -Verbose + $test = Get-SWNode -ComputerName $args[0] + If ($test) { + Write-Warning "Solarwinds node found, removing it..." + Remove-SWNode -ComputerName $args[0] + } + Else { + Write-Warning "Solarwinds node not found" + } + } + + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $ComputerName -Credential $Credential + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/README.md b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Scripts/DomainJoin_example.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Scripts/DomainJoin_example.ps1 new file mode 100644 index 0000000..a60580c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.General/Scripts/DomainJoin_example.ps1 @@ -0,0 +1,19 @@ +# figure out where to put it +$x = Get-ADComputer -Filter * -Server itdk12dc7.k12.nd.us -Credential $K12Cred -Properties CanonicalName + + + +# enter this on the machine itself +$Credential = Get-Credential +$AddComputerParams = @{ + DomainName = 'k12.nd.us'; + OUPath = 'OU=Prod,OU=All-General,OU=Computers,OU=ITD,DC=k12,DC=nd,DC=us' ; + Credential = $Credential; +} +Add-Computer @AddComputerParams + + + + + + diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/azure-pipelines.yml new file mode 100644 index 0000000..d1daf81 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.ITD-WindowsServer.Lifecycle' + +variables: + major: 0 + minor: 1 + 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.ITD-WindowsServer.Lifecycle.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.ITD-WindowsServer.Lifecycle.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/build.ps1 new file mode 100644 index 0000000..3e26294 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.ITD-WindowsServer.Lifecycle' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.ITD-WindowsServer.Lifecycle).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.nuspec b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.nuspec new file mode 100644 index 0000000..7cc64f5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.nuspec @@ -0,0 +1,12 @@ + + + + ITD.ITD-WindowsServer.Lifecycle + $VERSIONHERE$ + Zack Meier + Functions for Windows Server Lifecycle administration + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psd1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psd1 new file mode 100644 index 0000000..0c67215 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.ITD-WindowsServer.Lifecycle' +# +# Generated by: zmeier +# +# Generated on: 6/14/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.ITD-WindowsServer.Lifecycle.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + # ID used to uniquely identify this module + GUID = '42b3d283-1030-4bf9-afa7-4810061f74a8' + + # 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 Windows Server general administration' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psm1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/ITD.ITD-WindowsServer.Lifecycle.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep1.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep1.ps1 new file mode 100644 index 0000000..6e9386a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep1.ps1 @@ -0,0 +1,447 @@ +<# ################ +.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 + $NewVMWindowsAzureParams = @{ + ComputerName = 'itdzmtest901.nd.gov'; + CPU = 2; + MemoryGB = 8; + DiskOsGB = 128; + DiskDataGB = 0; + Subnet = '10.21.8.0/22'; + OS = "Windows Server 2025 Datacenter"; + Environment = 'Test'; + AppName = 'ITD-POC-zmeier'; + LicensingRestrictions = "No Licensing Restrictions"; + } + + New-ITDWindowsVmAzure @NewVMWindowsAzureParams -Credential $PrvCred -Verbose +.EXAMPLE + $NewVMWindowsAzureParams = @{ + ComputerName = 'itdzmtest701.nd.gov'; + ResourceGroupNameOverride = 'rg-shared-iis-tst'; + AvailabilityZone = 2; + CPU = 2; + MemoryGB = 8; + DiskOsGB = 128; + DiskDataGB = 0; + Subnet = '10.21.8.0/22'; + OS = 'Windows Server 2022 Datacenter'; + Environment = 'Test'; + AppName = 'ITD-POC-zmeier'; + LicensingRestrictions = "No Licensing Restrictions"; + } + + New-ITDWindowsVmAzure @NewVMWindowsAzureParams -Credential $PrvCred -Verbose +#> + +function New-ITDWindowsVmAzureStep1 { + [CmdletBinding()] + param ( + [string] + $FQDN, + + [string] + $ResourceGroupNameOverride, + + [string] + $AppName, + + [ValidateSet(1, 2, 3)] + [int] + $AvailabilityZone, + + [Parameter(ParameterSetName = 'VmSizeOverride')] + [string] + $VMSizeOverride, + + [Parameter(ParameterSetName = 'VmSizeDetermine')] + [int] + $CPU, + + [Parameter(ParameterSetName = 'VmSizeDetermine')] + [int] + $MemoryGB, + + [int] + $DiskOsGB, + + [int] + $DiskDataGB, + + [string] + $Subnet, + + [string] + $OS, + + [string] + $VMEnvironment, + + #[string] + #$Subscription, + + [string] + $LicensingRestrictions, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + $FQDN = $FQDN.ToLower() + $Hostname = $FQDN.split('.')[0] + + Write-Verbose -Message "Prepare Connections" + #$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' + #$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' + #$SecureStringPwd = '' #$Secret:AzureVMServicePrincipal #Pqt8Q~E-dDmQugcPPWdaK2t_4retS41VVVVOZbOx + #$SecureStringPwd = 'sQV8Q~sNLcrDl2RgB32gsSEsDVgdFhNMcBdPoaEX' + #$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) + #Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + + Write-Verbose -Message "Prepare Credentials" + $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password)) + + Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one" + Clear-DnsClientCache + $Cidr = $Subnet + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -Server 10.10.10.10 -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($null -ne $IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record." + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + Write-Verbose -Message ("FQDN is " + $FQDN) + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + #[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress + + [Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it." + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential + If ($null -eq $GuestVMLocalCredential) { + Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials" + $GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential + } + Else { + Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials" + } + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + + Write-Verbose -Message "Determine environment" + switch ($VMEnvironment) { + { $_ -eq 'Test' -or $_ -eq 'Development' } { + Write-Verbose -Message "Environment is Test or Development" + $EnvShortString = 'tst' + } + 'Production' { + Write-Verbose -Message "Environment is Production" + $EnvShortString = 'prd' + } + } + + Write-Verbose -Message "Determine subscription, via Subnet" + $AllSubscriptions = Get-AzSubscription + $AllAzVirtualNetworks = ForEach ($Subscription in $AllSubscriptions) { + Set-AzContext -SubscriptionObject $Subscription | Out-Null + Get-AzVirtualNetwork | ForEach-Object { + [PSCustomObject]@{ + Subscription = $Subscription.Name; + VirtualNetwork = $_ + } + } + } + + $Subscription = ($AllAzVirtualNetworks | Where-Object { $_.VirtualNetwork.Subnets.AddressPrefix -match $Subnet }).Subscription + $VirtualNetwork = ($AllAzVirtualNetworks | Where-Object { $_.VirtualNetwork.Subnets.AddressPrefix -match $Subnet }).VirtualNetwork + $VirtualNetworkSubnet = $VirtualNetwork.Subnets | Where-Object { $_.AddressPrefix -match $Subnet } + + $VNetName = $VirtualNetwork.Name + $VNetSubnet = $VirtualNetworkSubnet.Name + + Write-Verbose -Message "OS is $OS" + switch ($OS) { + { $_ -eq "Windows Server 2019 Datacenter" -or $_ -eq "Windows Server 2019" } { + Write-Verbose -Message "OS is Windows Server 2019" + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2019-Datacenter" + $SecurityType = '' + } + {$_ -eq "Windows Server 2022 Datacenter" -or $_ -eq "Windows Server 2022" } { + Write-Verbose -Message "OS is Windows Server 2022" + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "windowsserver2022" + $sku = "2022-datacenter" + $SecurityType = '' + } + { $_ -eq "Windows Server 2025 Datacenter" -or $_ -eq "Windows Server 2025" } { + Write-Verbose -Message "OS is Windows Server 2025" + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2025-datacenter" + $SecurityType = '' + } + "Windows 11 24H2" { + Write-Verbose -Message "OS is Windows 11 24H2" + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsDesktop" + $Offer = "Windows-11" + $sku = "win11-24h2-ent" + $SecurityType = '' + } + Default { Write-Error "Invalid operating system" -ErrorAction Stop } + } + + # finalize VM location and size + $location = "centralus" + + switch ($PSCmdLet.ParameterSetName) { + "VmSizeOverride" { + Write-Verbose -Message "ParameterSet is VmSizeOverride" + $VMSize = Get-AzVMSize -Location centralus | Where-Object { $_.Name -eq $VMSizeOverride } + } + "VmSizeDetermine" { + Write-Verbose -Message "ParameterSet is VmSizeDetermine" + $VMSizeFilter1 = @( + "Standard_D2ds_v5", + "Standard_D4ds_v5", + "Standard_D8ds_v5", + "Standard_D16ds_v5", + "Standard_D32ds_v5", + "Standard_E2ds_v5", + "Standard_E4ds_v5", + "Standard_E8ds_v5", + "Standard_E16ds_v5", + "Standard_E20ds_v5", + "Standard_E32ds_v5", + "Standard_F2s_v2", + "Standard_F4s_v2", + "Standard_F8s_v2", + "Standard_F16s_v2", + "Standard_F32s_v2" + ) + + $VMSize = Get-AzVMSize -Location centralus | ` + Where-Object { $VMSizeFilter1 -contains $_.Name } | ` + Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | ` + Where-Object Name -NotMatch "_Promo" | ` + Sort-Object NumberOfCores, MemoryInMB | ` + Select-Object -First 1 + } + } + + Write-Verbose -Message "Determine ResourceGroupName, and create Resource Group if needed" + If ($PSBoundParameters.ContainsKey('ResourceGroupNameOverride')) { + # use the name in the variable + Write-Verbose -Message "ResourceGroupName parameter found, is $ResourceGroupNameOverride" + $ResourceGroupName = $ResourceGroupNameOverride + } + Else { + Write-Verbose -Message "ResourceGroupName parameter not found, determine now" + # if name is not given, determine the name + $VMOwner = $AppName.split('-')[0].ToLower() + $VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " " + $ResourceGroupName = "rg-$VMOwner-$VMFunction-$EnvShortString" + } + Write-Verbose -Message "ResourceGroupName is $ResourceGroupName" + + Write-Verbose -Message "Change to selected subscription and validate resource group exists" + Set-AzContext $Subscription | Out-Null + $ResGroupExist = $null + $ResGroupExist = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue + + If (@($ResGroupExist).count -gt 1) { + Write-Error "Multiple Resource Groups matched" -ErrorAction Stop + } + If (@($ResGroupExist).count -lt 1) { + Write-Warning "No matching resource group found, creating it now" + New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Tag @{ApplicationName = $AppName } + } + If (@($ResGroupExist).count -eq 1) { + Write-Verbose -Message "Exactly one matching resource group found" + } + + $VMName = "vm-$HostName-$EnvShortString" + $VMIPConfigName = "ipconfig-$HostName-$EnvShortString" + $VMNicName = "nic-$HostName-$EnvShortString" + $VMObjectName = "vm-$HostName-$EnvShortString" + $VMOsDiskName = "vm-$HostName-os-$EnvShortString" + + Write-Verbose -Message "Verifying Applicable Inputs are Lowercase" + $VMIPConfigName = $VMIPConfigName.ToLower() + $VMNicName = $VMNicName.ToLower() + $VMObjectName = $VMObjectName.ToLower() + $VMOsDiskName = $VMOSDiskName.ToLower() + + Write-Verbose -Message "Creating IPConfig and NIC" + $IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $IPAddress.IPAddressToString -PrivateIpAddressVersion IPv4 -Subnet $VirtualNetworkSubnet + $VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $Location -Name $VMNICName -ResourceGroupName $ResourceGroupName -Subnet $VirtualNetworkSubnet -Force + $VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static" + $VMNIC.IpConfigurations[0].PrivateIpAddress = $IPAddress.IPAddressToString + Set-AzNetworkInterface -NetworkInterface $VMNIC + + Write-Verbose -Message "Build VM Config" + $vmConfigParams = @{ + VMName = $VMObjectName + VMSize = $VMSize.Name + } + + If ($PSBoundParameters.ContainsKey('AvailabilityZone')) { + Write-Verbose -Message "AvailabilityZone parameter found, adding to vmConfigParams" + $vmConfigParams += @{ + Zone = $AvailabilityZone + } + } + + $vmConfig = New-AzVMConfig @vmConfigParams + + # Security Profile + switch ($SecurityType) { + 'TrustedLaunch' { + Write-Verbose -Message "Security Profile is TrustedLaunch" + $vmConfig = Set-AzVMSecurityProfile -VM $vmConfig -SecurityType "TrustedLaunch" + } + '' { + Write-Verbose -Message "Security Profile is empty" + } + Default { + Write-Verbose -Message "Security Profile is null" + } + } + + $vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage + If ($VMOS -eq "Windows") { + $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $GuestVMLocalCredential + $vmConfig | Set-AzVMSourceImage -PublisherName $Publisher -Offer $Offer -Skus $Sku -Version latest + $vmConfig.OSProfile.ComputerName = $HostName + } + If ($VMOS -eq "Linux") { + $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $GuestVMLocalCredential + Switch ($VMSubscription) { + "npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" } + "infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" } + "prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" } + } + } + + $vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID + Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroupName + + Write-Verbose "Creating VM" + New-AzVM -VM $vmConfig -ResourceGroupName $ResourceGroupName -Location $Location -DisableBginfoExtension -LicenseType "Windows_Server" #-AsJob + + Write-Verbose -Message "New-AzVM completed, waiting 60 seconds before checking for completion" + Start-Sleep -Seconds 60 + + $VM = Get-AzVM -Name $VMObjectName -ResourceGroupName $ResourceGroupName + + If ($PSBoundParameters.ContainsKey("DiskDataGB")) { + $ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$VMEnvironment-") } }) + + $NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1 + $NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000") + $NewDiskName = "vm-$Hostname-app-$EnvShortString-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001 + + $LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1 + + $count = 0 + + If ($ExistingDisks) { + while ($Size -match $ExistingDisks.DiskSizeGB) { + $count++ + Write-Verbose -Message "DiskDataGB: $DiskDataGB, Count: $count" + If ($count -ge 11) { + Write-Error "Disk size not available" -ErrorAction Stop + } + Else { + $Size = $Size - 5 + } + } + } + + Write-Verbose -Message "DiskDataGB: $DiskDataGB, Count: $count" + + If ($null -ne $DiskDataGB -and $DiskDataGB -gt 0) { + $AzureRmDiskConfigParams = @{ + DiskSizeGB = $DiskDataGB + Location = $Location + CreateOption = "Empty" + SkuName = "Premium_LRS" + } + + If ($AvailabilityZone) { + Write-Verbose "VM is located in Availability Zone $Zone" + $AzureRmDiskConfigParams += @{Zone = $Zone } + } + #$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS + $DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams + + If (!(Get-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $NewDiskName -ErrorAction SilentlyContinue)) { + $NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroupName + + $VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -AsJob + } + } + } + + Write-Verbose -Message "Add networking tag to VM" -Verbose + $Tags = @{"Network"="StandardWindows"} + New-AzTag -ResourceId $VM.Id -Tag $Tags + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep2.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep2.ps1 new file mode 100644 index 0000000..3f09721 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmAzureStep2.ps1 @@ -0,0 +1,341 @@ +function New-ITDWindowsVMAzureStep2 { + [CmdletBinding()] + param ( + [string] + $FQDN, + + [string] + $AppName, + + [string] + $VMEnvironment, + + [PSCredential] + $Credential + ) + + begin { + $search = @() + #$Hostname = $VMName.split('-')[1] + $HostName = $FQDN.split('.')[0] + ###$VMEnvironment = $VMName.split('-')[2] #### + + Write-Verbose -Message ("Searching for Az VM name like " + $HostName) + Get-AzSubscription | ForEach-Object { + $Subscription = $_ + Set-AzContext $_ | Out-Null + $search += Get-AzVM | Where-Object Name -Like "*$HostName*" | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } } + } + } + + process { + switch (@($Search).count) { + { $_ -gt 1 } { Write-Error -Message "More than one virtual machine match found." } + { $_ -lt 1 } { Write-Error -Message "Less than one virtual machine match found." } + { $_ -eq 1 } { + Write-Verbose -Message "Prep VM variables" + $VMName = $search.Name + $ResourceGroupName = $search.ResourceGroupName + #$VMEnvironment = $VMName.split('-')[2] + $SubscriptionName = $search.SubscriptionName + Set-AzContext -Subscription $SubscriptionName + + $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + + Write-Verbose -Message "Set firewall tag" + $Tags = @{"Network"="StandardWindows"} + New-AzTag -ResourceId $VM.Id -Tag $Tags + + Write-Verbose -Message "Wait two minutes before Pre-Firewall Guest OS customization" + #Start-Sleep -Seconds 120 + + Write-Verbose -Message "Begin Pre-Firewall Guest OS customization" + $InvokeAzVMRunCommandParams = @{ + ResourceGroupName = $ResourceGroupName; + Name = $VMName; + CommandId = 'RunPowerShellScript' + } + + Write-Verbose -Message "1-Set WMI Tags" + $ScriptBlock = { + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "3-Disk Configuration" + $ScriptBlock = { + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "5-Time Zone" + $ScriptBlock = { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "6-Enable Performance Counters" + $ScriptBlock = { + # Enable Performance Counters + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + Write-Verbose -Message "7-Disable Windows Firewall" + $ScriptBlock = { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock + + # determine Active Directory Forest and OU + Write-Verbose -Message "8a-Determine domain join" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If ($null -eq $OUAppName) { + Write-Verbose -Message "Dedicated AppName OU for $AppName not found, placing in All-General OU" + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + Write-Verbose -Message ("OUAppName: " + $OUAppName.distinguishedName) -Verbose + + # Determine if the Environment sub-ou is special for the selected AppName + switch ($OUAppName.Name) { + 'Shared-PeopleSoft-HigherEd' { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Non-Prod" } + 'Production' { $EnvString = "Prod" } + } + } + 'Shared-PeopleSoft-State' { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Non-Prod" } + 'Production' { $EnvString = "Prod" } + } + } + Default { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Test" } + 'Production' { $EnvString = "Prod" } + } + } + } + + # Gather all sub OUs for the AppName OU + Write-Verbose -Message "EnvString is $EnvString" -Verbose + $SubOUs = Get-ADOrganizationalUnit -Server $DomainName -SearchBase $OUAppName -Filter * + Write-Verbose -Message ("SubOUs:") -Verbose + $SubOUs | ForEach-Object { Write-Verbose -Message $_.DistinguishedName -Verbose } + $LikeFilter = ("OU=$EnvString,OU=" + $OUAppName.Name + "*") + Write-Verbose -Message "LikeFilter: $LikeFilter" + $OUToUse = $SubOUs | Where-Object { $_.DistinguishedName -like $LikeFilter } + Write-Verbose -Message ("OUToUse: " + $OUToUse.distinguishedName) -Verbose + + <#$MatchFilter = ("OU=$EnvString,OU=" + $OUAppName.Name) + Write-Verbose -Message "MatchFiler: $MatchFilter" + $OutToUseMatch = ($SubOUs | Where-Object {$_.DistinguishedName -match "^$MatchFilter"}) + Write-Verbose -Message ("OUToUseMatch: " + $OUToUseMatch.distinguishedName) -Verbose +#> + # Determine if AD Computer object already exists + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $HostName } + If ($ExistingADComputer) { + Write-Verbose -Message "AD Object already exists in AD" + # Determine if AD Computer object is in the correct OU, or a sub-OU of the correct OU + If ($ExistingADComputer.DistinguishedName -like ("*" + $OUToUse.DistinguishedName)) { + Write-Verbose -Message "AD Object is in the correct OU, will attempt domain join" + $AttemptDomainJoin = $true + } + Else { + Write-Verbose -Message "AD Object is NOT in the correct OU, domain join will not occur, needs human review" + $AttemptDomainJoin = $false + } + } + Else { + $AttemptDomainJoin = $true + } + + If ($AttemptDomainJoin) { + $OuFinal = $OUToUse.DistinguishedName + Write-Verbose -Message "OuFinal: $OuFinal" -Verbose + + $FirstScriptBlock = { $DomainJoinCred = New-Object System.Management.Automation.PSCredential('svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) } + $SecondScriptText = 'Add-Computer -DomainName -OUPath "" -Credential $DomainJoinCred -Server itddc42.nd.gov -Verbose; Restart-Computer -Force -Verbose;' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + + #Write-Verbose -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + } + Write-Verbose -Message $InvokeVMScriptFunc.tostring() -Verbose ### + <# wait for firewall and reconnect + Write-Verbose -Message "8b-Verify if firewall is open before domain join attempt" + $connectivity = $false + while ($connectivity -eq $false) { + If ( (Test-NetConnection -ComputerName $FQDN).PingSuccedded) { + Write-Verbose -Message "Ping successful" -Verbose + $connectivity = $true + } + Else { + Write-Verbose -Message "Ping failed, may need to wait for PA IP sync" -Verbose + Start-Sleep -Seconds 60 + } + } + #> + Write-Verbose -Message "8c-Attempt domain join" + switch ($DomainName) { + 'nd.gov' { + Write-Verbose -Message "Attempting domain join nd.gov" + Write-Verbose -Message "Domain: $DomainName" + Write-Verbose -Message "OuPath: $OuFinal" + <#Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptPath 'C:\AzWinBuild\8-Domain-ndgov.ps1' -Parameter @{ + "DomainName" = 'nd.gov'; + "OuPath" = "$OuFinal" + }#> + $ScriptBlock = { + Param( + [string] + $DomainName, + + [string] + $OuPath + ) + + Write-Host $OuPath + Test-NetConnection -ComputerName nd.gov + + $DomainJoinCred = New-Object System.Management.Automation.PSCredential('ndgov\svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) + Add-Computer -DomainName $DomainName -OUPath $OuPath -Credential $DomainJoinCred + + Restart-Computer -Force + } + Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock -Parameter @{ + "DomainName" = 'nd.gov'; + "OuPath" = "$OuFinal" + } + #Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $InvokeVMScriptFunc + } + } + } + } + } + } + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep1.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep1.ps1 new file mode 100644 index 0000000..76c1b02 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep1.ps1 @@ -0,0 +1,529 @@ +<# +### step 1 +gather specs +provision virtual machine on hypervisor + +final result: + cpu configured, with hot-add + memory configured, with hot-add + disks 1, 2, and 3 attached with correct sizing + network connected + virtual machine powered on + + update SCTASK Step 1 completed + +### step 2 - customize Windows Guest OS + wait for SCTASK Step 1 completed message + configure + time zone, mount points, page file, etc + + update SCTASK Step 2 completed + +### step 3 - administration + wait for SCTASK Step 2 completed message + domain join + nd.gov at a minimum + install sccm + regardless if domain joined + + update SCTASK Step 3 completed + +### step 4 - validation + + + confirm all agents are installed + disks are present and formatted + +#> + +<# +.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 + $NewITDWindowsVmVMwareParams = @{ + ComputerName = 'itdzmtest300.nd.gov'; + CPU = 2; + MemoryGB = 8; + DiskOsGB = 50; + DiskSwapGB = 9; + DiskDataGB = 20; + Subnet = '10.11.12.0/23'; + OS = 'Windows Server 2022 Datacenter'; + Environment = "Test"; + Datacenter = "Bismarck"; + AppName = "ITD-POC-zmeier"; + StartupPriority = 4; + LicensingRestrictions = "No Licensing Restrictions"; + Credential = $PrvCred; + } + + New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams +#> + +function New-ITDWindowsVmVMwareStep1 { + [CmdletBinding()] + param ( + [string] + $FQDN, + + [int] + $CPU, + + [int] + $MemoryGB, + + [int] + $DiskOsGB, + + [int] + $DiskSwapGB, + + [int] + $DiskDataGB, + + [string] + $Subnet, + + [string] + $OS, + + [string] + $VMEnvironment, + + [string] + $Datacenter, + + [string] + $AppName, + + [int] + $StartupPriority, + + [string] + $LicensingRestrictions, + + [PSCredential] + $Credential + + ) + + begin { + + } + + process { + $FQDN = $FQDN.ToLower() + $HostName = $FQDN.split('.')[0] + + If ($VMEnvironment -eq "Development") { + $VMEnvironment = "Test" + } + + Write-Verbose -Message "Prepare Credentials and Connections" + $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password)) + + Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one" + Write-Verbose -Message "FQDN: $FQDN" -Verbose + Write-Verbose -Message "Hostname: $Hostname" -Verbose + + Clear-DnsClientCache + $InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred + $Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + ####### + ####### Remove 10.10.10.10 references when DNS sync is fixed + ####### + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue -Server 10.10.10.10).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($null -ne $IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose -Message "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, but does not match CIDR Block" + Break + } + } + Else { + Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record." + try { + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + Write-Verbose -Message ("FQDN is " + $FQDN) + } + catch { + + } + + + + ####### + ####### Review this code after DNS problems resolved - 2024/09/24 zm + ####### + ####### [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress + + [Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it." + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential + If ($null -eq $GuestVMLocalCredential) { + Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials" + $GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential + } + Else { + Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials" + } + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + + Write-Verbose -Message "Decide VMware Cluster and Licensing" + switch ($LicensingRestrictions) { + "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Enterprise" { $ClusterRoot = "SQLe" } + "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "SQLa" } + "IBM Websphere" { $ClusterRoot = "WAS" } + "Powerschool" { $ClusterRoot = "PS" } + "Pexip" { $ClusterRoot = "TEL" } + } + + Write-Verbose -Message "Decide Datacenter" + switch ($Datacenter) { + "Bismarck" { $ClusterInt = 1 } + "Mandan" { $ClusterInt = 2 } + } + + $Cluster = $ClusterRoot + $ClusterInt + Write-Verbose -Message "VMware Cluster is $Cluster, gathering metadata for $Cluster" + + switch ($Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "SQLa1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQLa1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLa1_FS92_Gen" + } + "SQLa2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQLa2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLa2_FS92_Gen" + } + "SQLe1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQLe1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLe1_FS92_Gen" + } + "SQLe2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQLe2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQLe2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + } + + Write-Verbose -Message "Validate entered disk sizes" + Write-Verbose -Message "DiskOsGB is $DiskOsGB. Validating its not a stupid number." -Verbose + switch ($DiskOsGB) { + { $_ -lt 50 } { + Write-Verbose -Message "DiskOsGB is 0 or below. Since an OS Disk is required, defaulting to 50GB" -Verbose + $DiskOsGB = 50 + } + } + + Write-Verbose -Message "DiskSwapGB is $DiskSwapGB. Validating its not a stupid number." -Verbose + switch ($DiskSwapGB) { + { $_ -le 0 } { + Write-Verbose -Message "DiskSwapGB is zero or below. Since an Swap Disk is required, defaulting to `$Memory + 1GB." -Verbose + $DiskSwapGB = ($MemoryGB + 1) + } + } + + Write-Verbose -Message "DiskDataGB is $DiskDataGB. Validating its not a stupid number." -Verbose + switch ($DiskDataGB) { + { $_ -le 0 } { + Write-Verbose -Message "DiskDataGB is 0. Since an Data Disk is optional, data disk will not be created." -Verbose + $DiskDataGB = 0 + } + { $_ -gt 500 } { + Write-Verbose -Message "DiskDataGB is 500GB or more. DiskDataGB will be set to the maximum of 500GB." -Verbose + $DiskDataGB = 500 + } + } + + Write-Verbose -Message "Determine Datastore / Datastore Cluster" + $DiskTotal = $DiskOsGB + $DiskSwapGB + $DiskDataGB + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + Write-Verbose -Message "Determine VMware VM Template for OS: $OS" + switch ($OS) { + "Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019" { $Template = "Windows Server 2019 Standard 1809.19" } + "Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard 1809.19" } + "Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Standard 1809.19" } + "Windows Server 2022" { $Template = "Windows Server 2022 Standard 2108.21" } + "Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Standard 2108.21" } + "Windows Server 2025" { $Template = "Windows Server 2025 Standard 24H2.6" } + Default { Write-Error "Invalid template option: $OS" -ErrorAction Stop } + } + + Write-Verbose -Message "Determine VMware Port Group" + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_*" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt) + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + Write-Verbose -Message "Configure Guest OS Customization Spec" + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + + Get-OSCustomizationSpec -Name 'Windows (Auto)' -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + + Set-Location C:\Temp + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $ComputeCluster.Name; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Location = $FolderLocation; + # Removed when using Content Library + #Template = $Template; + #OSCustomizationSpec = $OSSpec + } + + Get-ContentLibraryItem -Name $Template -Server $ViServer | New-VM @NewVMParams + $VM = Get-VM -Name $FQDN + $VM | Set-VM -OSCustomizationSpec $OSSpec -Confirm:$false + + Write-Verbose -Message "Set vCenter Tags on VM" + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category AppName -Name $AppName) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category DTAP -Name $VMEnvironment) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category LicensingRestrictions -Name $LicensingRestrictions) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category StartupPriority -Name $StartupPriority) -Server $VIServer + + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + + + Write-Verbose -Message "Config and Update Disks" + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + Write-Verbose -Message "Update Disk 1" + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $DiskOsGB) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $DiskOsGB -Confirm:$false + } + + Write-Verbose -Message "Config Disk 2" + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB ($MemoryGB + 1) ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $DiskSwapGB) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $DiskSwapGB -Confirm:$false + } + + Write-Verbose -Message "Config Disk 3" + If ($DiskDataGB -gt 0) { + Write-Verbose -Message "$DiskDataGB greater than zero" + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $DiskDataGB ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $DiskDataGB) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $DiskDataGB -Confirm:$false + } + } + + Write-Verbose -Message "Set VMware Tools Upgrade Policy to UpgradeAtPowerCycle" + $VMView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo + $vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle" + $VMView.ReconfigVM($vmConfigSpec) + + Write-Verbose -Message "Power On VM" + $VM | Start-VM + + Write-Verbose -Message "[$FQDN]:Step 1 End" + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep2.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep2.ps1 new file mode 100644 index 0000000..a5fa9c6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/New-ITDWindowsVmVMwareStep2.ps1 @@ -0,0 +1,667 @@ +<# +.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 + $NewITDWindowsVmVMwareParams = @{ + ComputerName = 'itdzmtest300.nd.gov'; + Environment = "Test"; + AppName = "ITD-POC-zmeier"; + Credential = $PrvCred; + } + + New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams +#> + +function New-ITDWindowsVmVMwareStep2 { + [CmdletBinding()] + param ( + [string] + $FQDN, + + [string] + $AppName, + + [string] + $VMEnvironment, + + [PSCredential] + $Credential + + ) + + begin { + + } + + process { + Write-Verbose -Message "Start New-ITDWindowsVmVMwareStep2" + $FQDN = $FQDN.ToLower() + $HostName = $FQDN.split('.')[0] + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + + $VM = Get-VM -Name $FQDN + $ViServer = $VM.Uid.split('@')[1].split(':')[0] + $VMTagAssignments = Get-TagAssignment -Entity $VM + + #$AppName = $VMTagAssignments | Where-Object { $_.Tag.Category.Name -eq "AppName" } + #$DTAP = $VMTagAssignments | Where-Object { $_.Tag.Category.Name -eq "DTAP" } + + Write-Verbose -Message "FQDN: $FQDN" + Write-Verbose -Message "HostName: $HostName" + + $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential -ErrorAction SilentlyContinue + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + + If ($null -eq $GuestVMLocalCredential) { + Write-Error -Message "Credentials not found in Passwordstate" -ErrorAction Stop + } + Else { + Write-Verbose -Message "Credentials found in Passwordstate" + Write-Verbose -Message ("username: + " + $GuestVMLocalCredential.UserName) + } + + <# Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } ## takes a long time to execute + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } #> + + + # OS + Write-Verbose -Message "Begin Post-Sysprep OS Guest Customization" + Write-Verbose -Message "Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking for DVD drive, and moving it to Z:\" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + Write-Host "hello1" + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking for unpartitioned space on C: volume and expanding" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + Write-Host "hello1" + # Expand C: Partition To Maximum Extent + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $Disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + If ($Disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + ForEach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + Else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." -Verbose + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." -Verbose + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." -Verbose + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." -Verbose + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." -Verbose + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Verbose -Message "Enabling Remote Management" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." -Verbose + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." -Verbose + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Checking current power plan, set to High Performance" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." -Verbose + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." -Verbose + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." -Verbose + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." -Verbose + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." -Verbose + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." -Verbose + } + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Verbose -Message "Enable the server manager performance monitors" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." -Verbose + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." -Verbose + } + } + catch { + Throw $_ + Break + } + } + + Write-Verbose -Message "Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." -Verbose + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." -Verbose + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." -Verbose + } + } + + # Active Directory + Write-Verbose -Message "Join Active Directory" + Write-Verbose -Message "Domain is $DomainName" + Write-Verbose -Message "AppName is $AppName" + + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + ### Shared-PeopleSoft-HigherEd is not found because of the extra space character in the OU name + ### commented out section below is the original code, swapped out for new code 2025/01/13 + + + + # Determine if the AppName has a dedicated OU, and pick it... or choose the All-General OU + If ($DomainName -eq 'nd.gov') { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If ($null -eq $OUAppName) { + Write-Verbose -Message "Dedicated AppName OU not found, placing in All-General OU" + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq "All-General" } + } + + # Determine if the Environment sub-ou is special for the selected AppName + switch ($OUAppName.Name) { + 'Shared-PeopleSoft-HigherEd' { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Non-Prod" } + 'Production' { $EnvString = "Prod" } + } + } + 'Shared-PeopleSoft-State' { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Non-Prod" } + 'Production' { $EnvString = "Prod" } + } + } + Default { + switch ($VMEnvironment) { + 'Test' { $EnvString = "Test" } + 'Production' { $EnvString = "Prod" } + } + } + } + + # Gather all sub OUs for the AppName OU + $SubOUs = Get-ADOrganizationalUnit -Server $DomainName -SearchBase $OUAppName -Filter * + If (@($SubOUs).count -eq 1) { + $OUToUse = $SubOUs + } + Else { + $OUToUse = $SubOUs | Where-Object { $_.DistinguishedName -like ("OU=$EnvString,OU=" + $OUAppName.Name + "*") } + } + + # Determine if AD Computer object already exists + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $HostName } + If ($ExistingADComputer) { + Write-Verbose -Message "AD Object already exists in AD" + # Determine if AD Computer object is in the correct OU, or a sub-OU of the correct OU + If ($ExistingADComputer.DistinguishedName -like ("*" + $OUToUse.DistinguishedName)) { + Write-Verbose -Message "AD Object is in the correct OU, will attempt domain join" + $AttemptDomainJoin = $true + } + Else { + Write-Verbose -Message "AD Object is NOT in the correct OU, domain join will not occur, needs human review" + $AttemptDomainJoin = $false + } + } + Else { + $AttemptDomainJoin = $true + } + + If ($AttemptDomainJoin) { + $OuFinal = $OUToUse.DistinguishedName + + $FirstScriptBlock = { $DomainJoinCred = New-Object System.Management.Automation.PSCredential('svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) } + $SecondScriptText = 'Add-Computer -DomainName -OUPath "" -Credential $DomainJoinCred -Server itddc42.nd.gov' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + + Write-Verbose -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + } + else { + $GuestCredentialAB = $GuestCredentialBB + } + <# + Write-Verbose -Message ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) + + Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + Write-Verbose -Message ("[$FQDN]:SCCM client copy complete " + (Get-Date)) + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Verbose -Message "[$FQDN]:Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Verbose -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $Credential -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + + Write-Verbose -Message "Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Verbose -Message "Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + <#Write-Verbose -Message "Waiting for network connectivity / Then KVM Activation..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + } + #> + Write-Verbose -Message ("[$FQDN]:Add to Solarwinds") + $Func = { + param($C) + Import-Module -Name ITDSolarwinds -Verbose + Import-SWDiscovery -ComputerName $C -Integration ServiceNow + } + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $FQDN -Credential $Credential + Write-Verbose -Message "[$FQDN]:End" + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/Remove-ITDWindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/Remove-ITDWindowsServer.ps1 new file mode 100644 index 0000000..b696091 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Public/Remove-ITDWindowsServer.ps1 @@ -0,0 +1,290 @@ +<# +.SYNOPSIS + Decomissions a Windows Server device +.DESCRIPTION + Decomissions a Windows Server device with ITD specifications (DNS/Infoblox, Active Directory, SCCM) +.NOTES + Credential must be an nd.gov account with access to remove objects on all platforms involved: DNS/Infoblox, Active Directory, SCCM. Read access to vCenter in the future. +.EXAMPLE + Remove-ITDWindowsServer -ComputerName itdxxx.nd.gov -SCTaskNum SCTASKxxxxxxxxx -Credential $AdminCredential +#> + +function Remove-ITDWindowsServer { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [string] + $SCTaskNum, + + [Parameter(Mandatory = $true)] + [PSCredential] + $Credential + ) + + begin { + $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password)) + } + + process { + $HostName = $ComputerName.split('.')[0] + + # get current user, SCTask, Ritm, custom variables + switch ($env:username) { + 'svcitdiaasauto' { + $assignTo = Get-ITDServiceNowUser -Username svcvmwareadm + } + Default { + $assignTo = Get-ITDServiceNowUser -Username $Env:username + } + } + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + + Write-Verbose -Message "Gathering $RitmNum" + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum -IncludeVariableSet -ErrorAction Stop + + ###### the name in the $ComputerName parameter must match a name in the form to continue + Write-Verbose -Message "Gathering VariableSet data from $RitmNum" + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($ComputerName -eq $TempCi.FQDN.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + $FQDN = $Ci.fqdn.display_value + + If ($MatchFound -eq $false) { + Write-Error -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -ErrorAction Stop + } + + Write-Verbose -Message "Assigning SCTask to current user, maybe" + ##### Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{assigned_to = $assignTo.name } REVIEW IF ASSIGNMENT SHOULD BE MADE HERE + $short_description = $SCTask.short_description.display_value + + # Gather DNS FQDN and IP + $DNSResolve = Resolve-DnsName -Name $ComputerName -ErrorAction SilentlyContinue + If ($DNSResolve -eq $null) { + $DNSResolve = "DNS object not found" + } + $DNSInfo = $DNSResolve | ConvertTo-Json -WarningAction SilentlyContinue + + # AD OU + $ADComputers = $null + $Domain = $ComputerName.Substring($ComputerName.IndexOf('.') + 1) + switch ($Domain) { + 'nd.gov' { + try { + $ADComputers = Get-ADComputer -Identity $HostName -Properties * -ErrorAction SilentlyContinue + } + catch { + # empty because erroraction silentlycontinue doesn't work as expected + } + If ($ADComputers) { + $ADInfo = $ADComputers | ConvertTo-Json -WarningAction SilentlyContinue + } + Else { + $ADInfo = "AD object not found" + } + } + 'Default' { + Write-Warning -Message "$ComputerName not nd.gov, review other domains manually" + } + } + + # SCCM collections + $SCCMResult = Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $Credential -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + Set-Location ITD:\ + $CMDevice = Get-CMDevice -Name $args[0] + If ($CMDevice) { + Get-ITDCMDeviceMemberOf -ComputerName $args[0] + } + Else { + "SCCM object not found" + } + } + $SCCMInfo = $SCCMResult | ConvertTo-Json -WarningAction SilentlyContinue + + Write-Verbose -Message "Updating SCTask with discovered information" + Update-ITDServiceNowRecord -ItemType "Catalog Task" -Number $SCTaskNum -Values @{work_notes = ("DNS Information: `n " + $DNSInfo) } + + If ($vCenterInfo) { + + } + If ($AzureInfo) { + + } + + Update-ITDServiceNowRecord -ItemType "Catalog Task" -Number $SCTaskNum -Values @{work_notes = ("Active Directory Information: `n " + $ADInfo) } + Update-ITDServiceNowRecord -ItemType "Catalog Task" -Number $SCTaskNum -Values @{work_notes = ("SCCM Information: `n " + $SCCMInfo) } + + $CommentsForWorkNotes = $null + + try { + $Notes = '
Decommissioned ' + (Get-Date -UFormat "%Y/%m/%d %H:%M:%S") + '
' + Write-Verbose -Message "All records with Title matching $ComputerName were marked as decommissioned in the Notes field." + Update-ITDPassword -Title $ComputerName -AppendNotes -Notes $Notes -Credential $Credential -Force + $CommentsForWorkNotes += ("`nPasswordstate: All records with Title matching $ComputerName were marked as decommissioned in the Notes field. ") + } + catch { + + } + + # Power off VM + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { + $hardware_platform = "VMware"; + $hardware_type = 'Virtual Machine' + + $VMs = Get-VM -Name $FQDN -ErrorAction SilentlyContinue | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + switch ( @($VMs).count ) { + { 0 } { + Write-Warning "$FQDN not found in vCenter... is it Azure? Or does it not exist?" + } + { $_ -gt 1 } { + Write-Verbose -Message "Multiple virtual machines with name $FQDN were found." + Write-Error -Message ("Multiple virtual machines with name $FQDN were found. Are there SRM placeholders? If so, unconfigure SRM and run this again. If there are no placeholders, confirm the virtual machine name.") -ErrorAction Stop + } + 1 { + Write-Verbose -Message 'One virtual machine with name $FQDN were found.' + $TagAssignment = Get-TagAssignment -Entity $VMs + $vCenterInfo = $TagAssignment | select Tag, Entity | ConvertTo-Json -Depth 1 + If ($VMs.PowerState -eq 'PoweredOn') { + Write-Verbose -Message "Power off VMware VM $FQDN" + $CommentsForWorkNotes += ("`nVMware: VM $FQDN has been powered off. ") + $VMs | Stop-VM -Confirm:$false + } + + If ($vCenterInfo) { + # enter work_notes into sctask + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("vCenter Information: `n " + $vCenterInfo) + } + } + } + } + } + { $_ -like "*Microsoft Virtual Machine*" } { + $hardware_platform = "Azure"; + $hardware_type = 'Virtual Machine' + } + { $_ -like "*HP*" } { + $hardware_platform = 'HPE'; + $hardware_type = 'Physical' + } + default { $hardware_platform = 'Other' } + } + + # SCCM removal + If ($SCCMResult -eq "SCCM object not found") { + # do nothing + } + Else { + Write-Verbose -Message "Attempt SCCM removal" + try { + $Domain = $ComputerName.Substring($ComputerName.IndexOf('.') + 1) + switch ($Domain) { + 'nd.gov' { $SCCMDomain = 'NDGOV' } + 'itd.nd.gov' { $SCCMDomain = 'NDGOV' } + 'k12.nd.us' { $SCCMDomain = 'K12' } + 'stg.k12.nd.us' { $SCCMDomain = 'K12STG' } + 'ndcloud.gov' { $SCCMDomain = 'NDCLOUD'} + } + + Write-Verbose -Message ("$Computername is SCCM Domain $SCCMDomain") + + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $Credential -ArgumentList $Hostname, $SCCMDomain -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + Set-Location ITD:\ + $Devices = Get-CMDevice -Name $args[0] | Where-Object Domain -EQ $args[1] + $Devices | select Name, Domain + ForEach ($Device in $Devices) { + If ($Device.Domain -match $SCCMDomain) { + Write-Verbose -Message ("SCCM: Removing " + $Device.Name + " on " + $Device.Domain + " domain") + $Device | Remove-CMDevice -Confirm:$false -Force + } + } + } + + $CommentsForWorkNotes += ("`nSCCM: Device named $Hostname was removed. ") + } + catch { + + } + } + + # Active Directory removal + If ($ADInfo -eq "AD object not found") { + # do nothing + } + Else { + try { + switch ($Domain) { + 'nd.gov' { + $ADComputers = Get-ADComputer -Identity $HostName + switch ( @($ADComputers).count ) { + { 0 } { "AD: Not found" } + { $_ -gt 1 } { "AD: More than one found" } + { 1 } { + Write-Verbose -Message "AD: One found, removing" + $ADComputers + $ADComputers | Remove-ADObject -Recursive -Credential $Credential -Confirm:$false + } + } + $CommentsForWorkNotes += ("`nActive Directory: AD computer object with name $Hostname was removed from the nd.gov domain. ") + + } + 'Default' { + Write-Warning -Message "$ComputerName not nd.gov" + } + } + } + catch { + + } + } + + # DNS removal + If ($DNSResolve -eq "DNS object not found") { + # do nothing + } + Else { + try { + Write-Verbose "Attempting DNS removal" + Remove-ITDIbDnsRecord -ComputerName $ComputerName -Credential $RadiusCred + $CommentsForWorkNotes += ("`nInfoblox: DNS A Record was removed for $ComputerName. ") + } + catch { + + } + } + + # Solarwinds removal + try { + Remove-ITDSolarwindsNode -ComputerName $ComputerName -Credential $Credential + $CommentsForWorkNotes += ("`nSolarwinds: Node was removed for $ComputerName. ") + } + catch { + + } + + $CommentsForWorkNotes += ("`n `nWindows OS Decommission completed. $hardware_platform $hardware_type hardware is ready for removal. ") + $HardwareRemovalDescription = ("$ComputerName $hardware_platform $hardware_type hardware is ready for removal.") + + Write-Verbose -Message "Add final comments for work notes into the SCTask, update the short_description for next workflow step" + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $CommentsForWorkNotes; + short_description = $HardwareRemovalDescription; + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/DomainJoin_example.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/DomainJoin_example.ps1 new file mode 100644 index 0000000..a60580c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/DomainJoin_example.ps1 @@ -0,0 +1,19 @@ +# figure out where to put it +$x = Get-ADComputer -Filter * -Server itdk12dc7.k12.nd.us -Credential $K12Cred -Properties CanonicalName + + + +# enter this on the machine itself +$Credential = Get-Credential +$AddComputerParams = @{ + DomainName = 'k12.nd.us'; + OUPath = 'OU=Prod,OU=All-General,OU=Computers,OU=ITD,DC=k12,DC=nd,DC=us' ; + Credential = $Credential; +} +Add-Computer @AddComputerParams + + + + + + diff --git a/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/PSU_errorchecking.ps1 b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/PSU_errorchecking.ps1 new file mode 100644 index 0000000..3b7c061 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.ITD-WindowsServer.Lifecycle/Scripts/PSU_errorchecking.ps1 @@ -0,0 +1,29 @@ +$Step1Complete = $null +$SCTaskNum = '' + +try { + $FQDN = 'itdcndhh22ywt.nd.gov' + $CIDR = '10.221.10.96/28' + + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Write-Verbose -Message "New-ITDWindowsVmVMwareStep1 function completed" + $Step1Complete = $true +} +catch { + #Write-Error -Message $error[0] + $Step1Complete = $false + + + $ErrorText = ($_.ErrorDetails.message | ConvertFrom-Json).text + If ($ErrorText -match "Cannot find 1 available IP address" ) { + $Msg = "Resolve the issue and resubmit the Server Build Request catalog item. Setting $SCTaskNum State to Closed Incomplete" + Write-Warning -Message $Msg + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ #> + work_notes = ("VMware build step 1 errored. $Msg. `nPSU Job Id #" + '52928' + " `n" + $ErrorText) + state = 'Closed Incomplete' + close_notes = ("VMware build step 1 errored. $Msg. `nPSU Job Id #" + '52928' + " `n" + $ErrorText) + } + + } + throw +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/azure-pipelines.yml new file mode 100644 index 0000000..85e8b87 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-ActiveDirectory.Object' + +variables: + major: 0 + minor: 1 + 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.Infra-ActiveDirectory.Object.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.Infra-ActiveDirectory.Object.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/build.ps1 new file mode 100644 index 0000000..c90551d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-ActiveDirectory.Object' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-ActiveDirectory.Object).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.nuspec new file mode 100644 index 0000000..e947c89 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-ActiveDirectory.Object + $VERSIONHERE$ + Zack Meier + Functions for Windows Server Active Directory User, Group, and Computer tasks + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psd1 new file mode 100644 index 0000000..8f70bd2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.Windows' +# +# Generated by: zmeier +# +# Generated on: 6/14/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.Infra-ActiveDirectory.Object.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = 'bfe6483c-14b2-42e9-8d98-62482eb4569c' + + # 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 Active Directory object (users and computers) administration' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psm1 new file mode 100644 index 0000000..d759833 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/ITD.Infra-ActiveDirectory.Object.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Disable-ITDADUser.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Disable-ITDADUser.ps1 new file mode 100644 index 0000000..d1e30d8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Disable-ITDADUser.ps1 @@ -0,0 +1,49 @@ +function Disable-ITDADUser +{ + [CmdletBinding()] + Param + ( + [string] + $Identity, + + [PSCredential] + $Credential + ) + + Begin + { + Write-Verbose "Validate credentials, stop script if invalid." + If($Credential -eq "" -or $Credential -eq $null) + { + $Credential = Get-Credential -Message "Enter domain/OU administrator credentials. User name must be entered as a SAMAccountName (DOMAIN\username) or as a User Principal Name (username@domain.com)" -UserName $Credential + If($Credential -eq "" -or $Credential -eq $null) + { + Write-Warning "credentials missing - stopping script" + break + } + If((Test-ADCredential -Credential $Credential -ErrorAction Stop) -eq $false) + { + Write-Warning "Invalid credentials or locked account." + break + } + } + Import-Module ActiveDirectory + } + Process + { + $OUdestination = "OU=DisabledAccounts,OU=USERS,OU=ITD,DC=ND,DC=GOV" + ForEach($username in $Identity) + { + + Write-Verbose "[$Username]:Processing" + $object = Get-ADUser -Identity $username + Write-Verbose "[$Username]:Disabling Object" + $object | Set-ADuser -Enabled $false -Credential $Credential + Write-Verbose "[$Username]:Moving Object" + $object | Move-ADObject -TargetPath $OUdestination -Credential $Credential + } + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADActiveServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADActiveServer.ps1 new file mode 100644 index 0000000..8fb83ff --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADActiveServer.ps1 @@ -0,0 +1,27 @@ +function Get-ITDADActiveServer +{ + [CmdletBinding()] + Param + ( + [int] + $ExpireAgeDays = 30 + ) + + Begin + { + Import-Module ActiveDirectory + $OUsource = "OU=ITD,DC=ND,DC=GOV" + $ExpireDate = (Get-Date).AddDays((-$ExpireAgeDays)) + } + Process + { + Get-ADComputer -SearchBase $OUsource -Filter * -Properties Name,CanonicalName,operatingSystem,operatingSystemServicePack,LastLogonDate,Enabled | ` + Where-Object operatingSystem -Like "*Server*" | ` + Where-Object LastLogonDate -GT $ExpireDate | ` + Where-Object Enabled -EQ $true | ` + Select-Object Name,operatingSystem,operatingSystemServicePack,LastLogonDate,CanonicalName + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADGroupMember.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADGroupMember.ps1 new file mode 100644 index 0000000..a2f7b90 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Get-ITDADGroupMember.ps1 @@ -0,0 +1,30 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +#> +function Get-ITDADGroupMember +{ + [CmdletBinding()] + Param + ( + [string] + $Identity + ) + + Begin + { + } + Process + { + return (Get-ADUser -Identity $Identity -Properties MemberOf).MemberOf + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADComputerServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADComputerServer.ps1 new file mode 100644 index 0000000..a4b43d7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADComputerServer.ps1 @@ -0,0 +1,68 @@ +<# +.Synopsis + Creates AD Computer object in ITD OUs +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +#> +function New-ITDADComputerServer +{ + [CmdletBinding()] + Param + ( + [string[]] + $ComputerName, + + #[string] + #$AppName, + + [PSCredential] + $Credential + ) + + Begin + { + + Write-Verbose "Validate credentials, stop script if invalid." + If($Credential -eq "" -or $Credential -eq $null) + { + $Credential = Get-Credential -Message "Enter domain/OU administrator credentials. User name must be entered as a SAMAccountName (DOMAIN\username) or as a User Principal Name (username@domain.com)" -UserName $Credential + If($Credential -eq "" -or $Credential -eq $null) + { + Write-Warning "credentials missing - stopping script" + break + } + If((Test-ADCredential -Credential $Credential -ErrorAction Stop) -eq $false) + { + Write-Warning "Invalid credentials or locked account." + break + } + } + + Import-Module ActiveDirectory + $OUdefault = "OU=Prod,OU=All-General,OU=Windows,OU=SERVERS,OU=COMPUTERS,OU=ITD,DC=ND,DC=GOV" + } + Process + { + ForEach($c in $ComputerName) + { + $Hostname=($c.split(".")[0]).ToUpper() + #If($AppName) + #{ + + #} + #Else + #{ + $OUdestination = $OUdefault + #} + + New-ADComputer -Name $Hostname -Path $OUdestination -Credential $Credential + } + } + End + { + } +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADGroup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADGroup.ps1 new file mode 100644 index 0000000..7f67772 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADGroup.ps1 @@ -0,0 +1,93 @@ +<# +.Synopsis + Create AD group within ITD GROUPS OU +.DESCRIPTION + Create Active Directory group within the ITD\ITD GROUPS OU, ability to add group members if needed +.EXAMPLE + New-ITDADGroup -SamAccountName ITD-GROUP-1 -Description "Sales group" +.EXAMPLE + New-ITDADGroup -SamAccountName ITD-GROUP-1 -Description "Sales group" -Members username1,username2,username3 +#> +function New-ITDADGroup +{ + [CmdletBinding()] + Param + ( + [Parameter(Mandatory=$true)] + [string] + $SamAccountName, + + [Parameter(Mandatory=$true)] + [string] + $Description, + + [string[]] + $Members, + + [PSCredential] + $Credential + ) + + Begin + { + Write-Verbose "Validate credentials, stop script if invalid." + If($Credential -eq "" -or $Credential -eq $null) + { + $Credential = Get-Credential -Message "Enter domain/OU administrator credentials. User name must be entered as a SAMAccountName (DOMAIN\username) or as a User Principal Name (username@domain.com)" -UserName $Credential + If($Credential -eq "" -or $Credential -eq $null) + { + Write-Warning "credentials missing - stopping script" + break + } + If((Test-ADCredential -Credential $Credential -ErrorAction Stop) -eq $false) + { + Write-Warning "Invalid credentials or locked account." + break + } + } + + Import-Module ActiveDirectory + } + Process + { + Write-Verbose "verify group object does not already exist, if it does, stop script" + $groupexists = Get-ADGroup -Filter {sAMAccountName -eq $SamAccountName} + If($groupexists) + { + Write-Warning "$SamAccountName already exists" + break + } + + Write-Verbose "fix description if needed" + If($Description -like "*1120*") + { + Write-Verbose "no change to description" + } + Else + { + Write-Verbose "adding '1120 - ' to description" + $Description = "1120 - " + $Description + } + + $OUdestination = "OU=ITDGROUPS,OU=GROUPS,OU=ITD,DC=ND,DC=GOV" + + Write-Verbose "create group in AD" + New-ADGroup -Name $SamAccountName ` + -SamAccountName $SamAccountName ` + -Description $Description ` + -DisplayName $SamAccountName ` + -GroupScope Global ` + -GroupCategory Security ` + -Path $OUdestination ` + -Credential $Credential + + Write-Verbose "Adding group members if applicable" + If($Members) + { + Add-ADGroupMember -Identity $SamAccountName -Members $Members -Credential $Credential + } + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccount.ps1 new file mode 100644 index 0000000..c4e4d11 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccount.ps1 @@ -0,0 +1,123 @@ +<# +.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 + Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines +#> + +function New-ITDADServiceAccount { + [CmdletBinding()] + param ( + [string] + $SamAccountName, + + [Parameter(Mandatory = $true)] + [string] + $Description, + + [Parameter(Mandatory = $true)] + [ValidateSet('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI')] + [string] + $PasswordstateList, + + [Parameter(Mandatory = $true)] + [string] + $PasswordstateTitle, + + [string] + $PasswordstateNotes, + + [pscredential] + $Credential + ) + + begin { + + } + + process { + Write-Verbose -Message "Verify if user object already exists in Active Directory" + try { + If (Get-ADUser -Identity $SamAccountName) { + $ADUserExists = $true + } + } + catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { + Write-Verbose -Message "Active Directory user object not found" + $ADUserExists = $false + } + catch { + Write-Error -Message "Unable to validate if samaccountname $SamAccountName is available" -ErrorAction $Stop + } + + Write-Verbose -Message "ADUser exists $ADUserExists" + + switch ($ADUserExists) { + Default { + Write-Error -Message "Unable to validate if samaccountname $SamAccountName is available" + } + $true { + Write-Error -Message "AD user object with $SamAccountName SamAccountName already exists." + } + $false { + Write-Verbose -Message "Create Passwordstate record" + $NewITDPasswordParams = @{ + PasswordList = $PasswordstateList; + Title = $PasswordstateTitle; + Description = $Description; + UserName = ("ndgov\$SamAccountName"); + Credential = $Credential; + } + + switch ($PSBoundParameters.Keys) { + PasswordStateNotes { + $NewITDPasswordParams.Notes = $PasswordstateNotes + } + } + + $NewITDPasswordResult = New-ITDPassword @NewITDPasswordParams -ErrorAction Stop + + If ($NewITDPasswordResult) { + Write-Verbose -Message "Create AD account" + $OuDestination = "OU=ITD SERVICE,OU=USERS,OU=ITD,DC=ND,DC=GOV" + + $DCtoUse = Get-ADDomainController -DomainName nd.gov -Discover -Site "Default-First-Site-Name" + + $NewADUserParams = @{ + Name = $SamAccountName; + SamAccountName = $SamAccountName; + UserPrincipalName = "$SamAccountName@nd.gov"; + Description = "1120 - $Description"; + Surname = "$SamAccountName"; + DisplayName = "$SamAccountName"; + Path = $OuDestination; + AccountPassword = $NewITDPasswordResult.Password; + PasswordNeverExpires = $true; + Enabled = $true; + Credential = $Credential; + Server = $DCtoUse; + } + + #try { + Write-Verbose -Message "Attempt New-ADUser" + New-ADUser @NewADUserParams + #} + #catch { + #Write-Error $error[0] + #} + } + + } + } + } + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountOLD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountOLD.ps1 new file mode 100644 index 0000000..dde2a0e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountOLD.ps1 @@ -0,0 +1,118 @@ +<# +.Synopsis + Create new account with random password, save in Passwordstate +.DESCRIPTION + Create new Active Directory user account in the "ITD SERVICE" OU, randomly generate a password, and save it in Passwordstate +.EXAMPLE + New-ITDADServiceAccount -SamAccountName !itdtest01 -Description "app/sql db account" -ComputerName itdtest01.nd.gov -PasswordStateList CSRC -Credential +#> +function New-ITDADServiceAccountOLD +{ + [CmdletBinding()] + Param + ( + [Parameter(Mandatory=$true)] + [string] + $SamAccountName, + + [Parameter(Mandatory=$true)] + [string] + $Description, + + [Parameter(Mandatory=$true)] + [string] + $ComputerName, + + [Parameter(Mandatory=$true)] + [ValidateSet("CSRC","CND","Linux","Office365","VMware","ZTEST")] + [string] + $PasswordstateList, + + [PSCredential] + $Credential + ) + + Begin + { + Write-Verbose "Validate credentials, stop script if invalid." + If($Credential -eq "" -or $Credential -eq $null) + { + $Credential = Get-Credential -Message "Enter domain/OU administrator credentials. User name must be entered as a SAMAccountName (DOMAIN\username) or as a User Principal Name (username@domain.com)" -UserName $Credential + If($Credential -eq "" -or $Credential -eq $null) + { + Write-Warning "credentials missing - stopping script" + break + } + If((Test-ADCredential -Credential $Credential -ErrorAction Stop) -eq $false) + { + Write-Warning "Invalid credentials or locked account." + break + } + } + + Write-Verbose "Confirm Passwordstate connection" + If((Test-NetConnection -ComputerName itdpv.nd.gov).PingSucceeded) + { + } + Else + { + Write-Warning "Passwordstate unavailable" + break + } + + Import-Module ActiveDirectory + } + Process + { + Write-Verbose "verify user account does not already exist, if it does, stop script" + $userexists = Get-ADUser -Filter {sAMAccountName -eq $SamAccountName} + If($userexists) + { + Write-Warning "$SamAccountName already exists" + break + } + + Write-Verbose "fix description if needed" + If($Description -like "*1120*") + { + Write-Warning "Do not enter '1120' into the description, this will be done for you" + Break + + } + + Write-Verbose "set OU, get passwordstate passwordlist information, set ADDescription" + $OUdestination = "OU=ITD SERVICE,OU=USERS,OU=ITD,DC=ND,DC=GOV" + $PStateList = Get-ITDPasswordstatePasswordList -Name $PasswordstateList + $ADDescription = "1120 - " + $Description + + <# removed 20181228 + Write-Verbose "Generate new password" + $PasswordGenerated = New-ITDRandomPassword + $PasswordSecured = $PasswordGenerated | ConvertTo-SecureString -AsPlainText -Force + + Write-Verbose "add to passwordstate" + $Date = Get-Date -UFormat "%Y/%m/%d @ %H:%M:%S" + $Notes = "Automatically generated by $env:USERNAME on $Date" + New-PasswordstateRecord -ListID $PStateList.ID -Title $ComputerName -Username "nd.gov\$SamAccountName" -APIkey $PStateList.APIkey -Password $PasswordGenerated -Description $Description -Notes $Notes + #> + + New-ITDPasswordstateRecord -Title $ComputerName -Description $ADDescription -PSList $PasswordstateList -Username $SamAccountName -GeneratePassword + + Write-Verbose "create account in AD" + New-ADUser -Name $SamAccountName ` + -SamAccountName $SamAccountName ` + -UserPrincipalName "$SamAccountName@nd.gov" ` + -Description $ADDescription ` + -DisplayName "$SamAccountName" ` + -Path $OUdestination ` + -AccountPassword $PasswordSecured ` + -PasswordNeverExpires $true ` + -Enabled $true ` + -Credential $Credential + + + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountRitm.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountRitm.ps1 new file mode 100644 index 0000000..d5761cc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/New-ITDADServiceAccountRitm.ps1 @@ -0,0 +1,88 @@ +<# +.SYNOPSIS + A short one-line action-based description, e.g. 'Tests if a function is valid' +.DESCRIPTION + Function will submit a ServiceNow Catalog Request of Application Server type with relevant information required for automated AD Service Account creation. +.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-ITDADServiceAccountRitm { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $RequestedForEmail, + + [Parameter(Mandatory = $true)] + [string] + $SamAccountName, + + [Parameter(Mandatory = $true)] + [ValidateSet('nd.gov')] + [string] + $ADDomain, + + [Parameter(Mandatory = $true)] + [string] + $Description, + + [Parameter(Mandatory = $true)] + #[ValidateSet('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI')] + [string] + $PasswordstateList, + + [Parameter(Mandatory = $true)] + [string] + $PasswordstateTitle + ) + + begin { + + } + + process { + # create Application Server RITM with json + + $AdditionalComments = "Please create a new $ADDomain Active Directory service account with the following details, following guidelines found in KB0016867.`n`n" + + $obj = [PSCustomObject]@{ + RequestedForEmail = $RequestedForEmail + SamAccountName = $SamAccountName; + ADDomain = $ADDomain; + PasswordstateTitle = $PasswordstateTitle; + PasswordstateList = $PasswordstateList; + Description = $Description; + } + + $AdditionalComments += ($obj | ConvertTo-Json -Compress) + + $NewITDServiceNowServiceCatalogRequest = @{ + CategoryItemName = 'Application Server'; + RequestedForEmail = $RequestedForEmail; + Values = @{ + additional_comments = $AdditionalComments; + request_type = "New"; + application_name = "Infra-ActiveDirectory.Object"; + environment = "Production"; + require_hosting_quote = 'No'; + add_change_disaster_recovery = 'No'; #> + vm_work_needed = 'No'; + + } + } + + $ReqResult = New-ITDServiceNowServiceCatalogRequest @NewITDServiceNowServiceCatalogRequest + } + + end { + Write-Output $ReqResult + } +} + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Unlock-ITDADAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Unlock-ITDADAccount.ps1 new file mode 100644 index 0000000..7c77bf5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Public/Unlock-ITDADAccount.ps1 @@ -0,0 +1,80 @@ +<# +.Synopsis + Unlock any Active Directory Account +.DESCRIPTION + Unlock any Active Directory Account, verify information +.EXAMPLE + Unlock-ITDADAccount -Identity username1 +.EXAMPLE + Unlock-ITDADAccount -Identity username1, username2, username3 +.EXAMPLE + Unlock-ITDADAccount -Identity username1 -Credential $PSCredential +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Unlock-ITDADAccount +{ + [CmdletBinding()] + Param + ( + [Parameter(Mandatory=$true)] + [string[]] + $Identity, + + [PSCredential] + $Credential + ) + + Begin + { + Write-Verbose "Validate credentials, stop script if invalid." + If($Credential -eq "" -or $Credential -eq $null) + { + $Credential = Get-Credential -Message "Enter domain/OU administrator credentials. User name must be entered as a SAMAccountName (DOMAIN\username) or as a User Principal Name (username@domain.com)" -UserName $Credential + If($Credential -eq "" -or $Credential -eq $null) + { + Write-Warning "credentials missing - stopping script" + break + } + If((Test-ADCredential -Credential $Credential -ErrorAction Stop) -eq $false) + { + Write-Warning "Invalid credentials or locked account." + break + } + } + + .3 + Import-Module ActiveDirectory + } + Process + { + ForEach ($i in $Identity) + { + $before = Get-ADUser -Identity $i -Properties SamAccountName,PasswordLastSet,lastLogonDate,Enabled,LockedOut | Select-Object SamAccountName,PasswordLastSet,lastLogonDate,Enabled,LockedOut + $SamAccountName = $before.SamAccountName + If($before.LockedOut -eq $false) + { + Write-Warning "[$SamAccountName]:Before:$before" + } + Else + { + Unlock-ADAccount -Identity $i -Credential $Credential + $after = Get-ADUser -Identity $i -Properties SamAccountName,PasswordLastSet,lastLogonDate,Enabled,LockedOut | Select-Object SamAccountName,PasswordLastSet,lastLogonDate,Enabled,LockedOut + Write-Warning "[$SamAccountName]:After:$after" + } + } + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/README.md b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountFromSCTask_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountFromSCTask_script.ps1 new file mode 100644 index 0000000..51b2103 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountFromSCTask_script.ps1 @@ -0,0 +1,147 @@ +[CmdletBinding()] +param ( + [string] + $SCTaskNum, + + [switch] + $Quiet +) + +begin { + $StartTime = Get-Date + New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred +} + +process { + $SCTaskSearch = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter ('active=true^short_description=Active Directory Service Account Provisioning') -Verbose + switch ($PSBoundParameters.Keys) { + 'SCTaskNum' { + $SCTaskSearch = $SCTaskSearch | Where-Object Number -EQ $SCTaskNum + } + } + + Switch (@($SCTaskSearch).count) { + { $_ -le 0 } { + Write-Verbose -Message "No Active Directory Service Account Provisioning tasks found." -Verbose + } + { $_ -ge 1 } { + Write-Verbose -Message ("Number of Active Directory Service Account Provisioning tasks found: " + @($SCTaskSearch).count) -Verbose + } + } + + ForEach ($SCTask in $SCTaskSearch) { + Clear-Variable -Name RITM, obj, NewITDADServiceAccountParams -ErrorAction SilentlyContinue + Write-Verbose -Message ("Start " + $SCTask.Num) + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId $SCTask.request_item.value -IncludeCustomVariable + $RitmRequestedFor = Get-ITDServiceNowUser -SysId $Ritm.requested_for.value + + $obj = ($Ritm.CustomVariable.additional_comments.Value -split "`n")[2] | ConvertFrom-Json + + If ($Obj.ADDomain -ne 'nd.gov') { + Write-Error -Message "Only nd.gov is supported, create account manually" -ErrorAction Stop + } + + $NewITDADServiceAccountParams = @{ + SamAccountName = $obj.SamAccountName; + Description = $obj.Description; + PasswordstateList = $obj.PasswordstateList; + PasswordstateTitle = $obj.PasswordstateTitle; + PasswordstateNotes = ("Requested via " + $RITM.number) + Credential = $PrvCred; #$Secret:svcitdiaasauto; + } + try { + New-ITDADServiceAccount @NewITDADServiceAccountParams -Verbose -ErrorAction Stop + $Notes = "New Active Directory account created." + $AccountCreated = $true + } + catch [Microsoft.PowerShell.Commands.WriteErrorException] { + Write-Error -Message $error[0] + $AccountCreated = $false + } + + + $EndTime = Get-Date + + If ($PSBoundParameters.ContainsKey('Quiet') -and $Quiet -eq $true) { + Write-Verbose -Message "Quiet mode enabled. No ServiceNow interactions will be done." -Verbose + } + Else { + Write-Verbose -Message "Quiet mode disabled. ServiceNow CHG will be generated." -Verbose + # create std chg and close it + switch ($AccountCreated) { + $true { + Write-Verbose -Message "AccountCreated true" -Verbose + Write-Verbose -Message "Generating SNow CHG" -Verbose + + #New-ITDServiceNowSession -Environment Test -Credential $Secret:SNowVMCred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = $RitmRequestedFor.user_name; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New nd.gov Active Directory service account created - $UAJobId, " + $RITM.number; + Description = "New nd.gov Active Directory service account created"; + Justification = "New nd.gov Active Directory service account required for zero-trust policies, following guidelines found in KB0016867"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Delete the new user account" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartTime + EndTime = $EndTime; + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RitmRequestedFor.user_name; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + + Update-ITDServiceNowRecord -ItemType "Change Request" -Number $CHG.Number.Value -Values @{ + work_notes = $Notes; + } + + Write-Verbose -Message ("Completing SNow " + $CHG.Number.value) -Verbose + $CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = ("New nd.gov Active Directory account " + $obj.ADDomain + "\" + $obj.SamAccountName + " created.") + } + Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose + + New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred + + Write-Verbose -Message ("SCTASK " + $SCTask.Num + " success notes") + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTask.Number -Values @{ + work_notes = $Notes + "`n" + ($Chg.Number.value + " created for the work."); + close_notes = $Notes; + state = "Closed Complete"; + } + } + $false { + Write-Verbose -Message "AccountCreated false" -Verbose + Write-Verbose -Message ("SCTASK " + $SCTask.Num + " failure notes") + $Message = "Error during account creation, requires human review. PSU Job Id #$UAJobId" + Write-Warning -Message $Message + Write-Verbose -Message ("Update " + $SCTask.Number) + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCtask.Number -Values @{ + work_notes = $Message; + short_description = $SCTask.short_description + " - HUMAN REVIEW" + } + } + Default { + Write-Verbose -Message "AccountCreated default" -Verbose + Write-Error -Message "AccountCreated variable is somehow not true or false... not sure how that happened. Great work!" + } + } + } + Write-Verbose -Message ("End " + $SCTask.Num) + } + + +} + +end { + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountRITM_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountRITM_script.ps1 new file mode 100644 index 0000000..38e2544 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccountRITM_script.ps1 @@ -0,0 +1,40 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true)] + [string] + $RequestedForEmail, + + [Parameter(Mandatory = $true)] + [string] + $SamAccountName, + + [Parameter(Mandatory = $true)] + [ValidateSet('nd.gov')] + [string] + $ADDomain, + + [Parameter(Mandatory = $true)] + [string] + $Description, + + [Parameter(Mandatory = $true)] + [ValidateSet('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI')] + [string] + $PasswordstateList, + + [Parameter(Mandatory = $true)] + [string] + $PasswordstateTitle +) + +$NewITDADServiceAccountParams = @{ + RequestedForEmail = $RequestedForEmail; + SamAccountName = $SamAccountName; + ADDomain = $ADDomain; + Description = $Description; + PasswordstateList = $PasswordstateList; + PasswordstateTitle = $PasswordstateTitle; +} + +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred -Verbose +New-ITDADServiceAccountRitm @NewITDADServiceAccountParams -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccount_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccount_script.ps1 new file mode 100644 index 0000000..fa338dd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/Scripts_PSU/New-ITDADServiceAccount_script.ps1 @@ -0,0 +1,78 @@ +[CmdletBinding()] +param ( + [string] + $SamAccountName, + + [Parameter(Mandatory = $true)] + [string] + $Description, + + [Parameter(Mandatory = $true)] + [ValidateSet('VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI', 'Office365')] + [string] + $PasswordstateList, + + [Parameter(Mandatory = $true)] + [string] + $PasswordstateTitle, + + [switch] + $Quiet +) + +$StartTime = Get-Date + +$NewITDADServiceAccountParams = @{ + SamAccountName = $SamAccountName; + Description = $Description; + PasswordstateList = $PasswordstateList; + PasswordstateTitle = $PasswordstateTitle; + Credential = $Secret:svcitdiaasauto; +} +try { + New-ITDADServiceAccount @NewITDADServiceAccountParams -Verbose +} +catch { + Write-Error -Message $error[0] -ErrorAction Stop +} + + +$EndTime = Get-Date +If ($PSBoundParameters.ContainsKey('Quiet') -and $Quiet -eq $true) { + Write-Verbose -Message "Quiet mode enabled. No ServiceNow interactions will be done." -Verbose +} +Else { + Write-Verbose -Message "Quiet mode disabled. ServiceNow CHG will be generated." -Verbose + # create std chg and close it + New-ITDServiceNowSession Test -Credential $Secret:SNowVMCred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = 'zmeier'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New nd.gov Active Directory service account created - $UAJobId"; + Description = "New nd.gov Active Directory service account created"; + Justification = "New nd.gov Active Directory service account required for zero-trust policies"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Delete the new user account" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartTime + EndTime = $EndTime; + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = 'zmeier'; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + + Update-ITDServiceNowRecord -ItemType "Change Request" -Number $CHG.Number.Value -Values @{ + work_notes = $Notes; + } + + Complete-ITDServiceNowChangeRequest -Number $CHG.Number.value -CloseCode "Successful" -CloseNotes "New nd.gov Active Directory account ndgov\$SamAccountName created." -Verbose +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/UD_PSU/NewITDADServiceAccountRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/UD_PSU/NewITDADServiceAccountRequest.ps1 new file mode 100644 index 0000000..eca739f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-ActiveDirectory.Object/UD_PSU/NewITDADServiceAccountRequest.ps1 @@ -0,0 +1,49 @@ +New-UDApp -Title 'SyncVMwareVMtoSharePoint' -Pages @( + New-UDPage -Name "Home" -Content { + New-UDForm -Content { + New-UDTypography -Text 'Enter the information below (all fields required) and click the Submit button' + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Label 'RequestedForEmail' -Id RequestedForEmail + New-UDTextbox -Label 'ADDomain' -Id ADDomain + New-UDTextbox -Label 'SamAccountName' -Id SamAccountName + New-UDTextbox -Label 'Description' -Id Description + New-UDTextbox -Label 'PasswordstateList' -Id PasswordstateList + New-UDTextbox -Label 'PasswordstateTitle' -Id PasswordstateTitle + } + } + } -OnValidate { + $FormContent = $EventData + + if ($EventData.RequestedForEmail -eq $null -or $EventData.RequestedForEmail -eq '' -or $EventData.ADDomain -eq $null -or $EventData.ADDomain -eq '' -or $EventData.SamAccountName -eq $null -or $EventData.SamAccountName -eq '' -or $EventData.Description -eq $null -or $EventData.Description -eq '' -or $EventData.PasswordstateList -eq $null -or $EventData.PasswordstateList -eq '' -or $EventData.PasswordstateTitle -eq $null -or $EventData.PasswordstateTitle -eq '') { + # ('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI') + New-UDFormValidationResult -ValidationError "All fields are required." + } + else { + if ($FormContent.ADDomain -ne 'nd.gov') { + New-UDFormValidationResult -ValidationError "Only nd.gov ADDomain is supported at this time." + } + else { + If (@('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI') -notcontains $EventData.PasswordstateList) { + New-UDFormValidationResult -ValidationError "PasswordstateList must match one of the following: VMware_Systems, Cohesity, VDI, Office365, CSRC, Shared Linux Password List, Peoplesoft Share PW" + } + } + New-UDFormValidationResult -Valid + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDADServiceAccountRitm_script.ps1'; + RequestedForEmail = $EventData.RequestedForEmail + ADDomain = $EventData.ADDomain + SamAccountName = $EventData.SamAccountName + Description = $EventData.Description + PasswordstateList = $EventData.PasswordstateList + PasswordstateTitle = $EventData.PasswordstateTitle + + } + $InvokePSUScriptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("ServiceNow Request " + $InvokePSUScriptResult.number + " created on behalf of $User" ) -Duration 100000 + + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/azure-pipelines.yml new file mode 100644 index 0000000..6425600 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-Certificate-External.Sectigo' + +variables: + major: 0 + minor: 1 + 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.Infra-Certificate-External.Sectigo.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.Infra-Certificate-External.Sectigo.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/build.ps1 new file mode 100644 index 0000000..0f52326 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-Certificate-External.Sectigo' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-Certificate-External.Sectigo).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Data/Config.json b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Data/Config.json new file mode 100644 index 0000000..0a0e8fb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Data/Config.json @@ -0,0 +1,14 @@ +{ + "AppConfig": { + + "AuthBaseAPIUrl": { + "Description": "API url for Sectigo - Authentication only", + "Value": "https://auth.sso.sectigo.com" + }, + + "BaseAPIUrl": { + "Description": "API url for Sectigo - Calls", + "Value": "https://admin.hard.sectigo.com" + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.nuspec new file mode 100644 index 0000000..409e79a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-Certificate-External.Sectigo + $VERSIONHERE$ + Freeman Peterson + Functions for Sectigo certificate enrollment and deployment + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psd1 new file mode 100644 index 0000000..0b210e5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.Infra-Certificate-External.Sectigo' +# +# Generated by: zmeier +# +# Generated on: 11/5/2025 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.Infra-Certificate-External.Sectigo.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + # ID used to uniquely identify this module + GUID = '5c65f13f-9bde-40d3-97ce-aa9b37883db2' + + # Author of this module + Author = 'fjpeterson' + + # Company or vendor of this module + CompanyName = 'State of North Dakota' + + # Copyright statement for this module + Copyright = '(c) 2026 fjpeterson. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'Functions for Sectigo certificate enrollment and deployment' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psm1 new file mode 100644 index 0000000..fb3c1d1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/ITD.Infra-Certificate-External.Sectigo.psm1 @@ -0,0 +1,25 @@ +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Private/Set-OnLoad.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Private/Set-OnLoad.ps1 new file mode 100644 index 0000000..046a913 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Private/Set-OnLoad.ps1 @@ -0,0 +1,37 @@ +# Using configuration file for most of the settings +$ConfigFile="${PSScriptRoot}/../Data/config.json" +$Config=(Get-Content -Path $ConfigFile|ConvertFrom-Json).AppConfig + +#Load Configuration File as Variables +$ConfigVars=($Config | Get-Member -Membertype Noteproperty).Name +ForEach ($ConfigVar in $ConfigVars) { + Set-Variable -Name $ConfigVar -Value $Config.${ConfigVar}.Value +} + +#Remove temporary variables we don't need to reused thse +Remove-Variable -Name Config,ConfigFile,ConfigVar,ConfigVars + +$TimeZone=(timezone).id + +# We need to declare the fields for syncing. +$SyncFields = @("Admins", "AgencyName","App","City","Cluster","Environment","SRM_Request","SRM_Status","SupportHours","TeamLead","VLAN","VMHost" ) +$SNSyncFields=@("Environment","AgencyName") + +#Default before set +$VerbosePreference = "SilentlyContinue" +$InformationPreference = "SilentlyContinue" +$DebugPreference = "SilentlyContinue" + +# Sets logging levels for cmdlets. +Switch ($VerboseLevel) { + 0 { $VerbosePreference = "SilentlyContinue" } + 1 { $VerbosePreference = "Continue" } + 2 { $VerbosePreference = "Continue" ; $InformationPreference = "Continue" } + 3 { $VerbosePreference = "Continue" ; $InformationPreference = "Continue"; $DebugPreference = "Continue" } +} + +# Overrides email SNMPTO +if ($TestMode -eq $True) { + Write-Information "Test Mode - On" + $SNMPTo = $TestModeAdmin +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Download-SectigoCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Download-SectigoCertificate.ps1 new file mode 100644 index 0000000..270d712 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Download-SectigoCertificate.ps1 @@ -0,0 +1,71 @@ + + #'x509' - for Certificate (w/ chain), PEM encoded, + #'x509CO' - for Certificate only, PEM encoded, + #'base64' - for PKCS#7, PEM encoded, + #'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded, + #'x509IOR' - for Intermediate(s)/Root only, PEM encoded, + #'pem' - for Certificate (w/ chain), PEM encoded, + #'pemco' - for Certificate only, PEM encoded, + #'pemia' - for Certificate (w/ issuer after), PEM encoded, + #'x509R' - for Certificate (w/ chain), PEM encoded. + # base64 is default. + +function Download-SectigoCertificate { + [CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$ApiToken=$env:SectigoToken, + [string]$CertRootPath="c:\certs", + [ValidateSet('x509','x509CO','base64','bin','x509IOR','pem','pemco','pemia','x509R' )] + [string]$Format="x509CO", + + [Parameter(Mandatory=$true)] + [string]$OrderId + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host "ApiToken:" + } + . $PSScriptRoot\..\Private\Set-Onload.ps1 + + [string]$CollectUrl = "${BaseAPIUrl}/api/ssl/v1/collect/${OrderId}?format=${format}" + + Write-Verbose -Verbose "CollectUrl: $CollectUrl" + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" # <-- Cleaned up syntax + } + + # --- API Call --- + Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId" + + try { + $response = Invoke-WebRequest -Uri $CollectUrl -Method Get -Headers $headers -UseBasicParsing -ErrorAction Stop + } catch { + Write-Error "API Request Failed: $($_.Exception.Message)" + return $null + } + $OutPath = "${CertRootPath}\cert_${OrderId}.cer" + + # --- Response Processing --- + if ($response.StatusCode -eq 200) { + Write-Verbose "Certificate successfully retrieved (Status 200)." + + # 1. Get the Hex String + # ASSUMPTION: The API returns the raw certificate Hex string in the response content. + # If the API returns JSON, you must use 'ConvertFrom-Json' first to extract the hex property. + $decimalNumbersString = $response.Content + +$numberStrings = $decimalNumbersString -split '\s+|,|\r?\n' | Where-Object { $_ } + +try { + [byte[]]$bytes = $numberStrings | ForEach-Object { [int]$_ } +} catch { + Write-Error "Error converting numbers. Ensure all numbers are between 0 and 255." + exit +} + +# Write the byte array to the binary file +[System.IO.File]::WriteAllBytes($OutPath , $bytes) +Get-ChildItem $OutPath|select fullname, LastWriteTime + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Enroll-SectigoCertificateRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Enroll-SectigoCertificateRequest.ps1 new file mode 100644 index 0000000..9af57b9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Enroll-SectigoCertificateRequest.ps1 @@ -0,0 +1,149 @@ +Function Enroll-SectigoCertificateRequest { + [CmdletBinding()] + param ( + [string]$ApiToken=$env:SectigoToken, + [int]$OrgId=8091, # 8091 friendly label is "Information Technology Department - Windows" + [Parameter(Mandatory=$true)] + [string]$subjAltNames, + [ValidateSet('IIS','IIS_OLD','IBM','LINUX','Apache','Tomcat')] + [string]$Type="IIS", + [string]$comment = "", + [Parameter(Mandatory=$true)] + [string]$dcvEmail, + [Parameter(Mandatory=$true)] + [ValidateSet('ECC',"RSA")] + [string]$KeyType, + [Parameter(Mandatory=$true)] + [string]$Csr, # Replace with your Sectigo Organization ID + [switch]$Test + ) + if (-Not $ApiToken) { + $ApiToken=Read-Host "ApiToken:" + } + +. $PSScriptRoot\..\Private\Set-Onload.ps1 + +[string]$RequestUrl= $BaseAPIUrl + "/api/ssl/v1/enroll" + +Write-Verbose -Verbose "RequestUrl: $RequestUrl" +#$CertType=2369 + +#If ($subjAltNames) { +$CertType=2375 +#} + + +$term=365 +# 7: IBM HTTP Server +# 14: Microsoft IIS 5 or 6 + switch ($ServerType.ToLower()) { + "iis" { + $ServerTypeCode = 35 + } + "iis_old" { + $ServerTypeCode = 14 + } + "ibm" { + $ServerTypeCode = 7 + } + "linux" { + $ServerTypeCode = 'Linux' + } + "apache" { + $ServerTypeCode = 2 + } + "tomcat" { + $ServerTypeCode = 12 + } + default { + Write-Warning "Unsupported server type: $ServerType. Please provide specific instructions for manual installation." + } + } + + +#ignorded for now +# keySize = 2048, +# keyParam = 2048, +# algorithm = $KeyType +# keyGenerationMethod = PK_AGENT + + +$body = @{ + orgId = $OrgId + subjAltNames = $subjAltNames + certType = $CertType + term = $term + serverType = $ServerTypeCode + comments = $comment + csr = $csr + externalRequester = $dcvEmail +} + +#$b2= @{ +# subjAltNames = $subjAltNames +#} +# +#if ($subjAltNames) { +# $body = $body + $b2 +#} + + + +$b3=@{ +commonName = $commonName +keySize = 2048 +keyParam = "2048" +algorithm = "RSA" +keyGenerationMethod = "PK_AGENT" +} + +$b4=@{ +commonName = $commonName +keyParam = "secp256r1" +algorithm = "ESS" +keyGenerationMethod = "PK_AGENT" +} + + + +# $body = $body + $b2 +#If ($KeyType -eq "rsa") { +# $body = $body + $b3 +#} else { +# $body = $body + $b4 +#} + + + + +If ($test) { + Return +} + +# Convert the body to JSON +$jsonBody = $body | ConvertTo-Json + +Write-Host $jsonBody + +# --- Set up Authentication Headers --- +$headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" +} + +# --- Send the Request --- +try { + $response=Invoke-RestMethod -Uri $RequestUrl -Method POST -Headers $headers -Body $jsonBody -ContentType "application/json" + + return $response +} +catch { + Write-Error "Error during certificate enrollment: $($_.Exception.Message)" + if ($_.Exception.Response) { + $errorResponse = $_.Exception.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $responseBody = $reader.ReadToEnd() + Write-Error "Sectigo API Error Response: $responseBody" + } +} +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoApiToken.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoApiToken.ps1 new file mode 100644 index 0000000..7a0787d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoApiToken.ps1 @@ -0,0 +1,46 @@ + + +Function Get-SectigoApiToken { + +#[CmdletBinding()] + +. $PSScriptRoot\..\Private\Set-Onload.ps1 +[string]$tokenEndpoint = $AuthBaseAPIUrl + "/auth/realms/apiclients/protocol/openid-connect/token" + +$clientId=$env:Sectigoclientid +$clientSecret=$env:SectigoclientSecret + +if (-Not $clientid) { + $clientid=Read-Host "Please enter your clientid" +} + +if (-Not $clientSecret) { + $clientSecret=Read-Host "Please enter your clientSecret" +} + +Write-Verbose -Verbose "tokenEndpoint: $tokenEndpoint " + +# Prepare the body for the token request +$body = @{ + grant_type = "client_credentials" + client_id = $clientId + client_secret = $clientSecret + +} + +. $PSScriptRoot\..\Private\Set-Onload.ps1 + +# Request the access token +try { + $tokenResponse = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Body $body -ContentType "application/x-www-form-urlencoded" + $accessToken = $tokenResponse.access_token + $env:SectigoToken=$accessToken + if ($accesstoken) { Write-Verbose -Verbose 'Token Set $ENV:SectigoToken'} + +} +catch { + Write-Error "Failed to obtain access token: $($_.Exception.Message)" + #exit 1 +} + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificate.ps1 new file mode 100644 index 0000000..6b409d7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificate.ps1 @@ -0,0 +1,37 @@ + +function Get-SectigoCertificate { + [CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$ApiToken=$env:SectigoToken, + [Parameter(Mandatory=$true)] + [string]$OrderId + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host "ApiToken:" + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + + # [string]$dcvUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}/dcv" + [string]$dcvUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}" + + + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" # <-- Cleaned up syntax + } + + # --- API Call --- + Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId" + + try { + $response = Invoke-RestMethod -Uri $dcvUrl -Method Get -Headers $headers -UseBasicParsing -ErrorAction Stop + return $response + } catch { + Write-Error "API Request Failed: $($_.Exception.Message)" + return $null + } + $response + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificateTypes.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificateTypes.ps1 new file mode 100644 index 0000000..2207eae --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoCertificateTypes.ps1 @@ -0,0 +1,42 @@ + + +function Get-SectigoCertificateTypes { + [CmdletBinding()] + param ( + [string]$ApiToken=$env:SectigoToken + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host "ApiToken:" + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + + [string]$CertificateTypesUrl= $BaseAPIUrl + "/api/ssl/v1/types" + Write-Verbose -Verbose "CertificateTypesUrl: $CertificateTypesUrl" + + # 1. Prepare the Authorization Header + # The Sectigo API usually requires the token in a Bearer authorization header. + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" + } + + # 2. Send the Request (GET is the standard method for listing resources) + $response = Invoke-WebRequest -Uri $CertificateTypesUrl -Method Get -Headers $headers -UseBasicParsing + + if ($response.StatusCode -eq 200) { + # 3. Process the Response + $certTypes = $response.Content | ConvertFrom-Json + + # ASSUMPTION: The API returns an array of objects, + # each representing a certificate type. + # This function returns the entire list/array. + return $certTypes + + } else { + Write-Error "Failed to get Certificate Types. Status code: $($response.StatusCode)." + Write-Error "Response content: $($response.Content)" + return $null + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoOrg.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoOrg.ps1 new file mode 100644 index 0000000..6bed1e3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoOrg.ps1 @@ -0,0 +1,44 @@ +# Load Configuration Variables + + +function Get-SectigoOrg { + [CmdletBinding()] + param ( + [string]$ApiToken=$env:SectigoToken + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + [string]$OrganizationLookupUrl=$BaseAPIUrl + "/api/organization/v1" + + # 1. Prepare the Authorization Header + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + +try { + # Invoke the web request to the Sectigo API + $Response = Invoke-WebRequest -Uri $OrganizationLookupUrl -Headers $Headers -Method GET + + # Check if the request was successful + if ($Response.StatusCode -eq 200) { + # Parse the JSON response + $Organizations = $Response.Content | ConvertFrom-Json + $Organizations|select-object id, name + $Organizations.departments + + } else { + Write-Error "Failed to retrieve organizations. Status Code: $($Response.StatusCode)" + Write-Error "Response Content: $($Response.Content)" + } +} +catch { + Write-Error "An error occurred during the API call: $($_.Exception.Message)" +} +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoSeverTypes.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoSeverTypes.ps1 new file mode 100644 index 0000000..305fc22 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Get-SectigoSeverTypes.ps1 @@ -0,0 +1,43 @@ +# Load Configuration Variables + + +function Get-SectigoSeverTypes { + [CmdletBinding()] + param ( + [string]$ApiToken=$env:SectigoToken + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + [string]$OrganizationLookupUrl=$BaseAPIUrl + "/api/v1/servertype" + + # 1. Prepare the Authorization Header + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" + } + + . $PSScriptRoot\..\Private\Set-Onload.ps1 + +try { + # Invoke the web request to the Sectigo API + $Response = Invoke-WebRequest -Uri $OrganizationLookupUrl -Headers $Headers -Method GET + + # Check if the request was successful + if ($Response.StatusCode -eq 200) { + # Parse the JSON response + $Response.Content | ConvertFrom-Json + + + } else { + Write-Error "Failed to retrieve organizations. Status Code: $($Response.StatusCode)" + Write-Error "Response Content: $($Response.Content)" + } +} +catch { + Write-Error "An error occurred during the API call: $($_.Exception.Message)" +} +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Revoke-SectigoCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Revoke-SectigoCertificate.ps1 new file mode 100644 index 0000000..71c3004 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Revoke-SectigoCertificate.ps1 @@ -0,0 +1,46 @@ + +function Revoke-SectigoCertificate { + [CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$ApiToken=$env:SectigoToken, + + [int]$reasonCode=4, + [Parameter(Mandatory=$true)] + [string]$reason, + [Parameter(Mandatory=$true)] + [string]$OrderId + ) + + if (-Not $ApiToken) { + $ApiToken=Read-Host + } + . $PSScriptRoot\..\Private\Set-Onload.ps1 + + [string]$RevokeUrl = "${BaseAPIUrl}/api/ssl/v1/revoke/${OrderId}" + +Write-Verbose -Verbose "RequestUrl: $RevokeUrl" + + $headers = @{ + "Authorization" = "Bearer $ApiToken" + "Content-Type" = "application/json" # <-- Cleaned up syntax + } + + $body = @{ + reasonCode = $reasonCode + reason = $reasonCode + } + + $jsonBody = $body | ConvertTo-Json + + # --- API Call --- + Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId" + + try { + $response=Invoke-RestMethod -Uri $RevokeUrl -Method POST -Headers $headers -Body $jsonBody -ContentType "application/json" + return $response + "Success" + } catch { + Write-Error "API Request Failed: $($_.Exception.Message)" + return $null + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Test-SectigoCertificateRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Test-SectigoCertificateRequest.ps1 new file mode 100644 index 0000000..902530c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/Public/Test-SectigoCertificateRequest.ps1 @@ -0,0 +1,39 @@ + +function Test-SectigoCertificateRequest { + [CmdletBinding(SupportsShouldProcess=$true)] + param ( + [string]$FilePath, + [string]$csr + ) + +if ($FilePath) { + [string]$csr = (Get-Content -Path $FilePath -Raw) +} + + [string]$dcvUrl = "https://certificates.nd.gov/api/csr/validate/string" + + + $headers = @{ + "accept" = "application/json" + "Content-Type" = "application/json" # <-- Cleaned up syntax + } + + $Body = @{ + "csr" = $csr + } + +$jsonBody = $body | ConvertTo-Json + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + # --- API Call --- + Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId" + + try { + $response = Invoke-RestMethod -Uri $dcvUrl -Method Post -Headers $headers -Body $jsonBody + $response + } catch { + Write-Error "API Request Failed: $($_.Exception.Message)"|convertfrom-json + return $null + } + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/README.md b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/README.md new file mode 100644 index 0000000..8200e54 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/README.md @@ -0,0 +1,122 @@ +# ITD.Infra-Certificate-Internal.Sectigo + +### Written by: Freeman Peterson fjpeterson@nd.gov + +# Description +This module is used to interact Sectigo API + +## Prerequisites +None + +# Api Documentation +https://www.sectigo.com/knowledge-base/detail/Sectigo-Certificate-Manager-SCM-REST-API/kA01N000000XDkE + +# Git repo +https://dev.azure.com/ndgov/NDIT-WindowsServerTeam/_git/ITD.Infra-Certificate-Internal.Sectigo + +# Install + +### Add Gallary +``` + Register-PSRepository -Name ITD_PwshGallery ` + -SourceLocation "https://powershell.nd.gov/ITD_PwshGallery/nuget/" ` + -PublishLocation "https://powershell.nd.gov/ITD_PwshGallery/nuget/" ` + -InstallationPolicy Trusted +``` + +### Install Module +``` +Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo|Install-Module -Scope CurrentUser +``` + +### Validate Module installed +``` +Get-Command -Module ITD.Infra-Certificate-Internal.Sectigo +``` +### Update Module +``` +Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo|Update-Module +``` + +# Examples and Information + +### Obtaining CSR From File +``` +$csr = (Get-Content -Path "c:\temp\hostname.csr" -Raw) +``` + +### Get Token Prompt for Creds +``` +$env:Sectigoclientid='b16d95fd-405f-4d41-a748-c1035916a359' +$env:SectigoclientSecret=redacted + +Get-SectigoApiToken +``` + + +### Test Cert Request +``` +Test-SectigoCertificateRequest -FilePath $csrpath +``` + +### Enroll the CSR +``` +$certRequest = Enroll-SectigoCertificateRequest -Csr $csr -dcvEmail 'youremail@nd.gov" #-Comment "app123" +``` + +### Get Cert Status +``` +Get-SectigoCertificate -Orderid $certRequest.sslid +``` + +### Wait for approval +``` +while ($certstatus -ne "Issued") { + $certstatus=(Get-SectigoCertificate -OrderId $certRequest.sslid).status + Sleep 1 +} +``` + +### Download Cert +``` +$CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format "pem").FullName +``` + +Default Format: Pem + 'x509' - for Certificate (w/ chain) PEM encoded + 'x509CO' - for Certificate only, PEM encoded + 'base64' - for PKCS#7, PEM encoded + 'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded + 'x509IOR' - for Intermediate(s)/Root only, PEM encoded + 'pem' - for Certificate (w/ chain), PEM encoded + 'pemco' - for Certificate only, PEM encoded + 'pemia' - for Certificate (w/ issuer after), PEM encoded + 'x509R' - for Certificate (w/ chain), PEM encoded + base64 + +### Add it to a cert store +As administrator: +``` + Import-Certificate -FilePath "C:\Certs\cert_OrderNumber.pem" -CertStoreLocation Cert:\LocalMachine\My +``` + +# Other functions + +### Revoke +``` +Revoke-SectigoCertificate -reasonCode 4 -reason "Just a test" -Orderid 11012388 +``` +No results will be given back to you. + +*If you revoke a cert you will no longer see them in Get-SectigoCertificate +Reason code (unspecified (0), keyCompromise (1), affiliationChanged (3), superseded (4), cessationOfOperation (5)) + +### Org Lookup +``` +Get-SectigoOrg +``` + +### Certificate Types +``` +Get-SectigoCertificateTypes +``` \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/certmgr-api-doc-25.8.html b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/certmgr-api-doc-25.8.html new file mode 100644 index 0000000..f0b764b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Certificate-External.Sectigo/certmgr-api-doc-25.8.html @@ -0,0 +1,41951 @@ + + + + + + + +Certificate Manager 25.8 REST API + + + + + + + +
+

Overview

+
+
+
+

The Sectigo Certificate Manager (SCM) REST API allows for the automation of many tasks normally done via the SCM UI. This includes:

+
+
+
    +
  • +

    issuance and management of SSL, client and device certificates

    +
  • +
  • +

    domain management

    +
  • +
  • +

    organization management

    +
  • +
  • +

    person management

    +
  • +
  • +

    discovery

    +
  • +
  • +

    reporting

    +
  • +
  • +

    ACME enrollment endpoints

    +
  • +
  • +

    network and MS agent management

    +
  • +
  • +

    admin management

    +
  • +
+
+
+

Requests to the SCM REST API are performed as an administrator so all results will be filtered based on the administrator’s role and privileges.

+
+
+
+
+

HTTP verbs

+
+
+

This API tries to adhere as closely as possible to standard HTTP and REST conventions in its +use of HTTP verbs.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
VerbUsage

GET

Used to retrieve a resource

POST

Used to create a new resource

PATCH

Used to update an existing resource, including partial updates

DELETE

Used to delete an existing resource

+
+
+
+

HTTP status codes

+
+
+

This API tries to adhere as closely as possible to standard HTTP and REST conventions in its +use of HTTP status codes.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Status codeUsage

200 OK

The request completed successfully

201 Created

A new resource has been created successfully. The resource’s URI is available from the response’s +Location header

204 No Content

An update to an existing resource has been applied successfully

400 Bad Request

The request was malformed. The response body will include an error providing further information

404 Not Found

The requested resource did not exist

+
+
+
+

Authorization

+
+
+

All API methods require HTTP headers for authentication. In addition, some API methods require certificate authentication as well. There are three authentication styles used by the API methods.

+
+
+

User Login via Password

+
+

Most API methods use this authentication style.

+
+
+

The required HTTP headers are:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
Header nameDescription

login

User login name

password

User password

customerUri

Customer URI part

+
+
+

User Login via Certificate

+
+

This can be used for all API methods except the APIs requiring Developer Login and is required by some APIs. In addition to the HTTP headers described below, the requests must have 'private' suffix in the URL, i.e. https://cert-manager.com/private/api/ssl/v1/types.

+
+
+

The required HTTP headers are:

+
+ ++++ + + + + + + + + + + + + + + + + +
Header nameDescription

login

User login name

customerUri

Customer URI part

+
+
+

Developer Login

+
+

Some APIs require this authentication style since a developer doesn’t need a user account. +The required HTTP headers are:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
Header nameDescription

email

Developer email address

password

Developer password

customerUri

Customer URI part

+
+
+
+
+

Errors

+
+
+

Whenever an error response (status code >= 400) is returned, the body will contain a JSON object +that describes the problem. The error object has the following structure:

+
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

code

Number

The error code

description

String

Error message

+
+

For example, a request that attempts to access resource with bad credentials will produce a +401 Unauthorized response:

+
+
+
+
HTTP/1.1 401 Unauthorized
+Content-Type: application/json
+Content-Length: 41
+
+{"code":-16,"description":"Unknown user"}
+
+
+
+

Possible values for JSON object fields include:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Error codeError message

-1

Unknown error.

-2

Internal error. Please contact Support for details.

-3

You are not authorized to perform {0}.

-7

{0} is required but missing.

-9

Unknown notification type: {0}

-9

The CSR is not valid Base-64 data!

-10

Error while decoding CSR.

-11

The CSR uses an unsupported algorithm!

-13

The CSR uses an unsupported key size!

-14

Unknown error.

-25

You are not authorized to execute {0}

-35

The Server type is invalid!

-36

The validity period (term) is invalid for this certificate profile.

-37

Access denied.

-39

{0}

-39

The certificate profile id is invalid!

-43

Internal error while decrypting.

-44

Error while generating key pair with open SSL

-62

Missing mandatory custom field!

-62

Invalid IP address {0}

-64

Optional field 'name' is invalid!

-65

Internal error {0}. Please contact Support for details.

-76

KU/EKU template is not allowed for customer.

-78

The public key is invalid or not supported.

-102

Only issued certificates could be revoked.

-103

Certificate has not been collected yet.

-105

Person not found.

-105

Error was occurred while renewing cert. Status = {0}

-107

Domain Control Validation is either incomplete or expired for {0}. Please complete it before requesting a certificate.

-109

Certificate is not available now, please try again later.

-110

Certificate has been revoked and cannot be downloaded.

-111

No certificate profile found by id {0}

-123

SSL Certificate to renew is invalid (null)

-124

Wrong SSL certificate id {0}.

-126

Unknown SSL certificate file format requested: {0}

-129

Connection error while applying certificate.

-130

SSL state is not ''ISSUED'': {0}

-131

Custom fields limit exceeded for customer.

-134

Custom field has to have unique name.

-135

Custom field cannot be found.

-138

Invalid CSR.

-140

CSR decoding temporarily unavailable. Please try again later.

-141

The public key size in the CSR should be {0} bits minimum.

-159

Your certificate already revoked

-159

Custom fields limit has been exceeded for this customer. Only {0} custom fields or fewer are allowed.

-160

You can''t create fields with the same name - {0}!

-164

Certificate cannot be enrolled for a Local Domain and/or Private IP for a validity period exceeding {0}.

-166

Entered data doesn''t match the certificate or no valid certificate found

-169

Certificate is not available, please contact administrator.

-170

Based on the customer configuration, ECC CSRs are not allowed.

-172

The Client Certificate Profile is invalid!

-176

Updating is not possible. List of your Client Certificate Profile was changed by super admin.

-180

This SSL Certificate Profile doesn''t allow renew

-181

Anchor Certificate details do not match to your request.

-183

Certificate is not collectable.

-184

Object has no available customized Client Certificate Profile.

-185

Customized Client Certificate Profile: {0} has no available terms.

-188

This user have already reached the maximum allowed number of valid certificates: {0}

-194

The CSR uses an unsupported key size.

-195

CA is not available now. Please try again later.

-196

Connection error while retrieving DCV email list.

-213

Old password is incorrect

-219

Cannot change the role of the only {0} user.

-220

Password can''t be the same.

-221

Please select at least one Organization/Department for each selected role

-222

Please select roles for the same level

-223

Please select only one Organization/Department for each selected role

-226

This Admin account does not have privileges required to manage ''{0}'' <org>.

-233

You have no privilege to create this admin user.

-234

You have no privilege to modify the privileges of this admin.

-237

Client Admin''s Email is invalid

-249

You cannot update this client admin which has already been deleted.

-253

You have no privilege to modify the role of this admin.

-255

Privilege "Allow DCV" can''t be added to non SSL admins.

-256

You have no privilege to assign DCV privileges.

-303

The range is too wide. Maximum of {0} public ip-port pairs and {1} private ip-port pairs per scan are allowed.

-304

Incorrect format CIDR.

-305

The range of ip-port pairs is too wide.

-306

Domain name {0} exceeds {1} characters limit.

-410

Customer {0} cannot be found.

-429

Customer {0} does not have a login name for CA.

-500

Person name cannot be empty

-507

You can''t change organization for this person.<br> Key escrow of its level has been enabled for either current organization/department or target organization/department.

-508

New person. Please specify name

-518

Unknown email address

-524

You have no privilege to modify the email of this person.

-607

Available Agent(s) are not configured to scan the specified private range(s).

-615

To scan, you must first enter at least one range parameter.

-618

Discovery is currently running. Please try again later.

-637

Available Agent(s) are not configured to scan the specified public range(s).

-639

Supplied orgid invalid..

-700

Such domain already exists

-705

This operation cannot be performed as the delegation status is other than ‘‘Requested’’.

-707

This domain delegation request has already been deleted.

-709

Please delegate domain to at least one organization or department.

-711

Domain can''t be delegated to deleted organization.

-712

The domain name should be at least {0} characters in length.

-713

The domain name should be at most {0} characters in length.

-714

The domain name should have at least {0} dots.

-715

The domain ''{0}'' is inactive.

-723

<Something> is not a high-level domain. Only high-level domains can be validated.

-724

The request for ''{0}'' cannot be processed since it''s domain validation status is {1}.

-727

The domain ''{0}'' does not exist.

-728

One or more delegations have been changed by another administrator. Your changes will be ignored.

-731

You do not have sufficient privileges to modify the name of this domain.

-732

Invalid domain name.

-737

The domain(s): {0} are not validated! Please perform the DCV process for them before proceed.

-738

Access denied. You are not allowed to perform the {0} operation on this domain.

-740

This operation cannot be performed due to SSL certificates enrolled for this domain or its subdomains.

-741

Access denied due to a DRAO’s request that has not been approved for domain {0}. Force domain creation is disabled.

-834

The changes of Client Certificate Profile settings will cause the following departments have <br> no available customized Client Certificate Profile, or customized Client Certificate Profiles have no available term or default term: {0}

-840

The changes of Client Certificate Profile settings will cause the under levels have <br> no available customized Client Certificate Profile, or customized Client Certificate Profiles have no available term or default term.

-843

SSL certificate of this type cannot be requested due to ‘{0}’ validation status of the selected organization.

-951

'At least one of the following fields must be filled in: {0}.

-970

Incorrect login credentials.

-976

New password must be between {0} and 32 characters.

-977

New password length must be 32 characters.

-982

New password must not contain Login.

-1010

Domain ''{0}'' is not allowed.

-1021

This operation cannot be performed for Organization ''{0}''.

-1023

Organization ''{0}'' not found.

-1104

Invalid order number {0}

-1108

No valid client certificates found for {0}.

-1112

Certificate can''t be approved cause it has state = {0}

-1113

{0} certificate is not ready to be applied. + Current certificate state is {1}.

-1117

The SSL is null.

-1137

The domain(s) {0} have not been validated under the DCV procedure.

-1138

Error while checking size of public key in CSR.

-1140

Since you are a requester of this certificate you can''t approve it. For EV certificates the requester and the approver must not be the same person.

-1144

SSL certificate id: {0} must be re-discovered due to migration need. We are sorry for inconvenience.

-1148

Replace is forbidden for autoinstalled certificates.

-1400

The request is being processed by Sectigo.

-1450

Unsupported certificate format specified: {0}

-1601

Field ''{0}'' has invalid value.

-1603

Error while validating the domain {0}

-1608

DCV is not enabled for this customer.

-3114

This {0} was modified or deleted by another user.

-3115

This {0} was modified or deleted by another user. Please refresh data.

-3301

Invalid scan range: {0}

-5001

You don' t have access to Organization assigned to the Rule

-5002

Assignment rules cannot be empty.

-5003

Cannot delete. An assignment rule has been assigned to the Net Discovery Tasks {0}

-5101

Certificate not found. {0}

-5109

Device Certificate Profile not found.

+
+
+
+

Date formatting

+
+
+

The dateFormat parameter allows you to specify the format in which date and time values are serialized in the API responses. You can pass either the name of an enum or the format string associated with an enum from the following list.

+
+
+

Supported Date Formats

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionParameter nameFormatExample

ISO 8601 (International Standard)

ISO

yyyy-MM-dd

2024-07-10

ISO_HMS

yyyy-MM-dd’T’HH:mm:ss.SSS’Z'

2024-07-10T14:30:00.000Z

European Format (Day-Month-Year)

EU

dd.MM.yyyy

10.07.2024

EU_HMS

dd.MM.yyyy HH:mm:ss

10.07.2024 14:30:00

US Format (Month-Day-Year)

US

MM/dd/yyyy

07/10/2024

US_HMS

MM/dd/yyyy HH:mm:ss

07/10/2024 14:30:00

UK Format (Day-Month-Year with Slashes)

UK

dd/MM/yyyy

10/07/2024

UK_HMS

dd/MM/yyyy HH:mm:ss

10/07/2024 14:30:00

Japan Format (Year-Month-Day)

JP

yyyy/MM/dd

2024/07/10

JP_HMS

yyyy/MM/dd HH:mm:ss

2024/07/10 14:30:00

+
+
+

Usage

+
+

It is possible to use the dateFormat in two case-independent ways:

+
+
+
    +
  • +

    Parameter name

    +
  • +
+
+
+

Example

+
+
+
+
GET /api/resource?dateFormat=eu
+
+
+
+

or

+
+
+
+
GET /api/resource?dateFormat=EU
+
+
+
+
    +
  • +

    Format

    +
  • +
+
+
+

Example

+
+
+
+
GET /api/resource?dateFormat=dd.mm.yyyy
+
+
+
+

or

+
+
+
+
GET /api/resource?dateFormat=dd.MM.yyyy
+
+
+
+
+
+

API reference

+
+

SSL Certificates

+
+
+

Used to perform operations on SSL certificates. SSL certificates are identified by an ID field, usually known as sslId in this API.

+
+
+

SSL helper APIs

+
+

List SSL certificate profiles

+
+

List SSL certificate profiles, previously known as a certificate type. An enrollment request will require the certificate profile be specified.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

organizationId

Filter by Organization ID (optional)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/types?organizationId=510' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer703' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst703'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of available SSL Certificate Profiles

[].id

Number

Certificate Profile ID

[].name

String

Certificate Profile name

[].useSecondaryOrgName

Boolean

Use secondary Organization name

[].description

String

Certificate Profile description

[].terms

Array

Terms (in days) available for the Certificate Profile

[].keyTypes

Object

Key types available for the Certificate Profile

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 210
+
+[ {
+  "id" : 1134,
+  "name" : "SSL SASP 523912935",
+  "description" : "SSL SASP 1587542533",
+  "terms" : [ 365 ],
+  "keyTypes" : {
+    "RSA" : [ "1024", "2048", "4096" ]
+  },
+  "useSecondaryOrgName" : false
+} ]
+
+
+
+
+
+

List SSL certificate custom fields

+
+

List SSL certificate custom fields. An enrollment require will require all mandatory custom fields be specified.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/customFields' -i -X GET \
+    -H 'login: admin_customer715' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst715' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of custom fields

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatory

Boolean

Is field mandatory

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 64
+
+[ {
+  "id" : 54,
+  "name" : "testName",
+  "mandatory" : true
+} ]
+
+
+
+
+
+
+

SSL certificate Locations

+
+

List SSL certificate locations

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/location
ParameterDescription

sslId

Certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/144/location' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1024' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1024'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of SSL Certificate Locations

[].id

Number

Location ID

[].locationType

String

Location Type

[].name

String

Location Name (optional)

[].details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 209
+
+[ {
+  "id" : 56,
+  "locationType" : "CUSTOM",
+  "name" : "",
+  "details" : {
+    "IP" : "1.1.1.1"
+  }
+}, {
+  "id" : 57,
+  "locationType" : "CUSTOM",
+  "name" : "",
+  "details" : {
+    "alias" : "value"
+  }
+} ]
+
+
+
+
+
+

Create custom location for SSL certificate

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/location
ParameterDescription

sslId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/133/location' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer917' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst917' \
+    -d '{
+  "details" : {
+    "Server" : "Apache"
+  }
+}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of the created certificate location entity

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/ssl/v1/133/location/53
+
+
+
+
+
+

Get details of SSL certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/location/{locationId}
ParameterDescription

sslId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/143/location/55' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1014' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1014'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Location ID

locationType

String

Location Type

name

String

Location Name (optional)

details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 101
+
+{
+  "id" : 55,
+  "locationType" : "CUSTOM",
+  "name" : "",
+  "details" : {
+    "IP" : "1.1.1.1"
+  }
+}
+
+
+
+
+
+

Update SSL certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/location/{locationId}
ParameterDescription

sslId

Certificate ID

locationId

Location ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/173/location/58' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1262' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1262' \
+    -d '{
+  "details" : {
+    "Server" : "Apache"
+  }
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete SSL certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/location/{locationId}
ParameterDescription

sslId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/135/location/54' -i -X DELETE \
+    -H 'login: admin_customer933' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst933'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

View SSL certificates

+
+

List SSL certificates

+
+

List all SSL certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

commonName

Filter by Common Name

subjectAlternativeName

Filter by Subject Alternative Name

status

Filter by status. Possible values: ', 'Invalid', 'Requested', 'Approved', 'Declined', 'Applied', 'Issued', 'Revoked', 'Expired', 'Replaced', 'Rejected', 'Unmanaged' - deprecated, result will be empty, 'SAApproved', 'Init''

sslTypeId

Filter by Certificate Profile ID

discoveryStatus

Filter by discovery status. Possible values: 'NotDeployed', 'Deployed' (deprecated, see "requestedVia").

vendor

Filter by Vendor

orgId

Filter by Organization ID

installStatus

Filter by Install status. Possible values: 'NONE', 'NOT_STARTED', 'KEY_PROCESSING', 'KEY_READY', 'CERT_PROCESSING', 'SCHEDULED', 'INSTALLING', 'ACTION_REQUIRED', 'READY_FOR_INSTALL', 'NEED_SERVER_RESTART', 'COMPLETED', 'INVALID'

renewalStatus

Filter by Renewal status. Possible values: 'NOT_SCHEDULED', 'SCHEDULED', 'STARTED', 'SUCCESSFUL', 'FAILED'

issuer

Filter by Issuer

serialNumber

Filter by Serial Number

requester

Filter by Requester

externalRequester

Filter by External Requester

signatureAlgorithm

Filter by Signature Algorithm

keyAlgorithm

Filter by Key Algorithm

keySize

Filter by Key Size filter (deprecated, see "keyParam")

keyParam

Filter by Key Size / Curve Name

sha1Hash

Filter by SHA1 Hash

md5Hash

Filter by MD5 Hash

sha256Hash

Filter by SHA256 Hash

keyUsage

Filter by Key Usage

extendedKeyUsage

Filter by Extended Key Usage

requestedVia

Filter by Requested Via. Possible values: 'WEB_FORM', 'CLIENT_ADMIN', 'API', 'DISCOVERY', 'IMPORTED', 'SCEP', 'CD_AGENT', 'MS_AGENT', 'MS_CA', 'BULK_REQUEST', 'ACME', 'EST', 'REST'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1152' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1152'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of SSL certificates available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested ssls

[].sslId

Number

SSL ID

[].commonName

String

SSL Common Name

[].subjectAlternativeNames

Array

SSL Subject Alternative Names

[].serialNumber

String

SSL Serial Number

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 53
+
+[ {
+  "sslId" : 162,
+  "commonName" : "ccmqa.com"
+} ]
+
+
+
+
+
+

Count SSL certificates

+
+

Count all SSL certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

commonName

Common Name

subjectAlternativeName

Subject Alternative Name

status

Filter by Status. Possible values: ', 'Invalid', 'Requested', 'Approved', 'Declined', 'Applied', 'Issued', 'Revoked', 'Expired', 'Replaced', 'Rejected', 'Unmanaged' - deprecated, result will be empty, 'SAApproved', 'Init''

sslTypeId

Filter by certificate Profile ID

discoveryStatus

Filter by discovery status. Possible values: 'NotDeployed', 'Deployed' (deprecated, see "requestedVia").

vendor

Filter by Vendor

orgId

Filter by Organization ID

installStatus

Filter by Install status. Possible values: 'NONE', 'NOT_STARTED', 'KEY_PROCESSING', 'KEY_READY', 'CERT_PROCESSING', 'SCHEDULED', 'INSTALLING', 'ACTION_REQUIRED', 'READY_FOR_INSTALL', 'NEED_SERVER_RESTART', 'COMPLETED', 'INVALID'

renewalStatus

Filter by Renewal status. Possible values: 'NOT_SCHEDULED', 'SCHEDULED', 'STARTED', 'SUCCESSFUL', 'FAILED'

issuer

Filter by Issuer

serialNumber

Filter by Serial Number

requester

Filter by Requester

externalRequester

Filter by External Requester

signatureAlgorithm

Filter by Signature Algorithm

keyAlgorithm

Filter by Key Algorithm

keySize

Filter by Key Size filter (deprecated, see "keyParam")

keyParam

Filter by Key Size / Curve Name

sha1Hash

Filter by SHA1 Hash

md5Hash

Filter by MD5 Hash

keyUsage

Filter by Key Usage

extendedKeyUsage

Filter by Extended Key Usage

requestedVia

Filter by Requested Via. Possible values: 'WEB_FORM', 'CLIENT_ADMIN', 'API', 'DISCOVERY', 'IMPORTED', 'SCEP', 'CD_AGENT', 'MS_AGENT', 'MS_CA', 'BULK_REQUEST', 'ACME', 'EST', 'REST'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1' -i -X HEAD \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer827' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst827'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of SSL certificates available according to the filtering applied

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 42
+
+
+
+
+
+

Get SSL certificate details

+
+

Get SSL certificate details.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}
ParameterDescription

sslId

Certificate ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/71' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer631' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst631'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

sslId

Number

An ID using which this certificate can be renewed or revoked through Enrollment form. Deprecated. Use 'id' instead

id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

orderNumber

Number

The obsolete parameter for the order identifier under which the certificate request has been processed. backendCertId should be used instead

backendCertId

String

Certificate ID in enrolling backend

vendor

String

The name of the issuing CA

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

subType

String

SSL Subtype, available only for managed certificates. Deprecated, will be removed in favor of validationType

validationType

String

Validation type, available only for managed certificates

term

Number

Term (days)

owner

String

The approver of the request for this certificate

ownerId

Number

The approver ID of the request for this certificate

requester

String

Requester

requesterId

Number

The Requester ID, when available

requestedVia

String

Requested Via. Possible values: 'Enrollment Form', 'Client Admin', 'Web API', 'Discovery', 'Imported', 'SCEP', 'CD Agent', 'MS Agent', 'MS CA', 'Bulk Request', 'ACME', 'EST', 'REST API'

externalRequester

String

External Requester, when available

comments

String

Comments

requested

String

Requested date

approved

String

Approved date

issued

String

Issued date

declined

String

Declined date

expires

String

Expiration date

replaced

String

Replaced date

revoked

String

Revocation date

reasonCode

Number

Revocation reason code provided on revoke to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

renewed

Boolean

Renewal indicator

renewedDate

String

Renewal date

serialNumber

String

SSL Serial Number

signatureAlg

String

Signature Algorithm

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

keyUsages

Array

Key Usages

extendedKeyUsages

Array

Extended Key Usages

subjectAlternativeNames

Array

Subject alternative names

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value. For input type 'DATE' format is yyyy-MM-dd

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

autoInstallDetails

Object

Auto-Installation Information

autoInstallDetails.state

String

Auto-Installation state

autoInstallDetails.nodes[]

Array

Auto-Installation nodes (planned or already installed to)

autoInstallDetails.nodes[].name

String

Node name

autoInstallDetails.nodes[].port

Number

Node port

autoRenewDetails

Object

Auto-Renewal Information

autoRenewDetails.state

String

Auto-Renewal state

autoRenewDetails.daysBeforeExpiration

Number

Days before expiration to start auto-renewal

suspendNotifications

Boolean

Suspend Notifications for the certificate

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 1324
+
+{
+  "commonName" : "ccmqa.com",
+  "sslId" : 71,
+  "id" : 71,
+  "orgId" : 487,
+  "status" : "Issued",
+  "orderNumber" : 7344326,
+  "backendCertId" : "7344326",
+  "vendor" : "Vendor",
+  "certType" : {
+    "id" : 1125,
+    "name" : "SSL SASP -636901162",
+    "description" : "SSL SASP 879220013",
+    "terms" : [ 365 ],
+    "keyTypes" : {
+      "RSA" : [ "1024", "2048", "4096" ]
+    },
+    "useSecondaryOrgName" : false
+  },
+  "validationType" : "Organization Validation (OV)",
+  "term" : 365,
+  "owner" : "client-admin-636 client-admin-636",
+  "ownerId" : 322,
+  "requester" : "634_nobody@nobody.sectigo.com",
+  "requestedVia" : "Enrollment Form",
+  "comments" : "some comments",
+  "requested" : "08/15/2025",
+  "expires" : "08/15/2026",
+  "renewed" : false,
+  "serialNumber" : "00:0::11::2:2::33",
+  "keyAlgorithm" : "RSA",
+  "keySize" : 2048,
+  "keyType" : "RSA - 2048",
+  "subjectAlternativeNames" : [ "ccmqa.com" ],
+  "customFields" : [ {
+    "name" : "name1",
+    "value" : "value1"
+  } ],
+  "certificateDetails" : {
+    "issuer" : "issuer",
+    "sha1Hash" : "AAABBBCCC",
+    "sha256Hash" : "7fbdaa891e461c286ecce7a92a8fb7fa89a5ce0cef813b3fd4b221c69b38388a"
+  },
+  "autoInstallDetails" : {
+    "state" : "Not configured"
+  },
+  "autoRenewDetails" : {
+    "state" : "Not scheduled"
+  },
+  "suspendNotifications" : false
+}
+
+
+
+
+
Get SSL certificate DCV details
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/dcv
ParameterDescription

sslId

Certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/142/dcv' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1006' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1006'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

dcvLog

Object

DCV Log

dcvLog.error

Object

Error details

dcvLog.error.code

Number

Error code

dcvLog.error.description

String

Error description

dcvLog.log

Array

DCV Log

dcvLog.log[].dcvStatus

String

DCV Status

dcvLog.log[].domainName

String

Domain Name

dcvLog.log[].dcvDate

String

DCV Date

dcvLog.log[].lastCheck

String

Last check

dcvLog.log[].nextCheck

String

Next check

dcvLog.log[].dcvEmailRefNumber

Number

EMAIL DCV reference number

instructions

Array

DCV Instructions

instructions[].domainName

String

Domain Name

instructions[].dcvMode

String

DCV Mode

instructions[].host

String

DNS DCV host part

instructions[].point

String

DNS DCV point part

instructions[].url

String

HTTP/S DCV file url

instructions[].file

String

HTTP/S DCV file content

instructions[].dcvEmail

String

EMAIL DCV admin contact email

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 574
+
+{
+  "dcvLog" : {
+    "error" : {
+      "code" : 0,
+      "description" : null
+    },
+    "log" : [ {
+      "dcvStatus" : "Awaiting Validation",
+      "domainName" : "ccmqa.com",
+      "lastCheck" : "2025-08-15 09:09:01",
+      "nextCheck" : "2025-08-15 10:09:01",
+      "dcvDate" : null,
+      "dcvEmailRefNumber" : 1
+    } ]
+  },
+  "instructions" : [ {
+    "domainName" : "ccmqa.com",
+    "dcvMode" : "CNAME",
+    "host" : "_4E380094C3B3B40C69203451D32E78D3.ccmqa.com.",
+    "point" : "7A16100AAE509FE98CE5AC6D6F04AC81.151A1EB4B2324F07D2BDCDB6D02452D2.sectigo.com."
+  } ]
+}
+
+
+
+
+
+
Recheck SSL certificate DCV details
+
+

Initiate recheck of SSL certificate DCV details on CA.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}/dcv/recheck
ParameterDescription

sslId

Certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/166/dcv/recheck' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1202' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1202'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 202 Accepted
+Content-Type: application/json;charset=UTF-8
+Content-Length: 331
+
+{
+  "dcvLog" : {
+    "error" : {
+      "code" : 0,
+      "description" : null
+    },
+    "log" : [ {
+      "dcvStatus" : "Awaiting Validation",
+      "domainName" : "ccmqa.com",
+      "lastCheck" : "2025-08-15 09:09:01",
+      "nextCheck" : "2025-08-15 10:09:01",
+      "dcvDate" : null,
+      "dcvEmailRefNumber" : 1
+    } ]
+  }
+}
+
+
+
+
+
+
+
+

Enroll SSL certificate

+
+

Request SSL certificate

+
+

Submit request for a new SSL certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

csr

String

Certificate signing request

'Must match the regular expression [a-zA-Z0-9-=\/\s],Must not be empty,Size must be between 1 and 32767 inclusive'

subjAltNames

String

Subject alternative names (comma separated)

certType

Number

Certificate Profile ID

term

Number

Certificate validity period in days

'Must be at least 1'

comments

String

Comments for enroll request

'Maximum length is 1024 characters or can be empty'

customFields[]

Array

Custom fields to be applied to requested certificate. Must contain mandatory custom fields.

customFields[].name

String

Name of an enabled custom field.

[]

customFields[].value

String

Value of the custom field.

[]

externalRequester

String

External Requester. Acceptable format: 'email@domain.com' or 'email1@domain.com, email2@domain.com'

'Maximum length is 512 characters or can be empty'

dcvMode

String

DCV validation mode. Possible values: [CNAME, EMAIL, HTTP, HTTPS, TXT]. Required in case of disabled DCV pre-validation.

dcvEmail

String

DCV validation email. Required in case of EMAIL DCV mode.

'Must be a well-formed email address'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/enroll' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer647' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst647' \
+    -d '{
+  "orgId" : 491,
+  "subjAltNames" : "ccmqa.com",
+  "certType" : 1129,
+  "term" : 365,
+  "comments" : "test",
+  "externalRequester" : "",
+  "customFields" : [ {
+    "name" : "custom field",
+    "value" : "custom field value"
+  } ],
+  "dcvMode" : "EMAIL",
+  "dcvEmail" : "admin@ccmqa.com",
+  "csr" : "-----BEGIN CERTIFICATE REQUEST-----\nMIICyTCCAbECAQAwgYMxCzAJBgNVBAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzAN\nBgNVBAcMBk9kZXNzYTERMA8GA1UECgwIQWR2YW5jZWQxCzAJBgNVBAsMAklUMRIw\nEAYDVQQDDAljY21xYS5jb20xHjAcBgkqhkiG9w0BCQEWD25teXphQGNjbXFhLmNv\nbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMHZo0lPzCqBVu03qHJa\np2wbOyN8kvdkU2VRj+GaF2APgrQps/sepvhyralxa9w5WD5KyoXhnM+7DPCsqDxK\nkxsBjEliLQqXwmoiai0A2DMmjWCoSMopzNTIORLPn8GaWFJSEtCa+9D1EXD2UZjS\nY/8MN0fEAIqaXFUrfW3cqW/QUjZH0mlJumUqQjtZY0DnAQsCxxZUlsHCkKEHuEQu\n5WhY8ys1/RANaoJmRh2xZuFMOZ71kLkwi5fvReqxjkRRHwG9cYDyurTNYmjkaICN\n/hqUwk9VKkW0G5ol8t0xau8RuHdDHi5Wb/R6+d/G+8/kn0BoOqseABih1+FYs+Ws\nK8UCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQA15aWRLayIuUZmPhdrpJXQAtrw\nAoeYYwp5hvaTLwZBWEg5n+ZhH5SaSCpt+53QW3+jiT8jTsPKAqyvgSQI0MVi8o5J\nJhig6pPHGSKbfxmvmfSwxK4F9W2GNVcdICX+Js0BB5UXsZB4k1gTRr1VdICNiCDc\nDZAC0+HhkZSU9StD43T9ac3gZIfEEepX9WBx9QbBASbUZ1ziSBfGKA7vnQHbC9lT\nphLa2SvCSozmG36vYMV+Ak5YWnrp2c1Jhcd8PE0TIW6yPT+D6UvcZWb+KHfw2KAH\nVXPNFSgSZkMzFBMQJH9UcfyvPX5+7qXakxAhLS/zKOg7Y601cRg5/Eqa0Z59\n-----END CERTIFICATE REQUEST-----"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

renewId

String

Renew id

sslId

Number

SSL id

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 56
+
+{
+  "sslId" : 72,
+  "renewId" : "SwtLTSwRitETQXEKXTrq"
+}
+
+
+
+
+
+

Request SSL certificate with Private Key Agent

+
+

Submit request for a new SSL certificate with generated keypair. Private key will be generated on the Private Key Agent.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

commonName

String

Certificate common name

'Must not be null,Size must be between 1 and 64 inclusive'

subjAltNames

String

Subject alternative names (comma separated)

certType

Number

Certificate Profile ID

term

Number

Certificate validity period in days

'Must be at least 1'

comments

String

Comments for enroll request

'Maximum length is 1024 characters or can be empty'

algorithm

String

Keypair algorithm

Possible values: RSA, EC

keySize

Number

Keypair key size (deprecated, see "keyParam")

Applied only in case keypair algorithm is specified.

keyParam

String

Keypair key size (for RSA) or curve name (for EC)

Applied only in case keypair algorithm is specified.

customFields[]

Array

Custom fields to be applied to requested certificate. Must contain mandatory custom fields.

customFields[].name

String

Name of an enabled custom field.

[]

customFields[].value

String

Value of the custom field.

[]

externalRequester

String

External Requester. Acceptable format: 'email@domain.com' or 'email1@domain.com, email2@domain.com'

'Maximum length is 512 characters or can be empty'

keyGenerationMethod

String

Key generation method

Possible values: [PK_AGENT, AZURE_KEY_VAULT]

passPhrase

String

Password to protect PKCS#12 certificate.(Only for Private Key agent key generation)

'Size must be between 8 and 64 inclusive'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/enroll-keygen' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer659' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst659' \
+    -d '{
+  "orgId" : 495,
+  "subjAltNames" : "ccmqa.com",
+  "certType" : 1133,
+  "term" : 365,
+  "comments" : "test",
+  "externalRequester" : "",
+  "customFields" : [ {
+    "name" : "custom field",
+    "value" : "custom field value"
+  } ],
+  "commonName" : "ccmqa.com",
+  "passPhrase" : "password",
+  "keySize" : 2048,
+  "keyParam" : "2048",
+  "algorithm" : "RSA",
+  "keyGenerationMethod" : "PK_AGENT"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

renewId

String

Renew id

sslId

Number

SSL id

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 56
+
+{
+  "sslId" : 74,
+  "renewId" : "k1UFQF1ZJpsAAER71Tjh"
+}
+
+
+
+
+
+

Request SSL certificate with Azure KeyVault

+
+

Submit request for a new SSL certificate with generated keypair. Private key will be generated in Azure KeyVault.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

commonName

String

Certificate common name

'Must not be null,Size must be between 1 and 64 inclusive'

subjAltNames

String

Subject alternative names (comma separated)

certType

Number

Certificate Profile ID

term

Number

Certificate validity period in days

'Must be at least 1'

comments

String

Comments for enroll request

'Maximum length is 1024 characters or can be empty'

algorithm

String

Keypair algorithm

Possible values: RSA, EC

keySize

Number

Keypair key size (deprecated, see "keyParam")

Applied only in case keypair algorithm is specified.

keyParam

String

Keypair key size (for RSA) or curve name (for EC)

Applied only in case keypair algorithm is specified.

customFields[]

Array

Custom fields to be applied to requested certificate. Must contain mandatory custom fields.

customFields[].name

String

Name of an enabled custom field.

[]

customFields[].value

String

Value of the custom field.

[]

externalRequester

String

External Requester. Acceptable format: 'email@domain.com' or 'email1@domain.com, email2@domain.com'

'Maximum length is 512 characters or can be empty'

keyGenerationMethod

String

Key generation method

Possible values: [PK_AGENT, AZURE_KEY_VAULT]

azureKeyVault

Object

Azure Key Vault settings

azureKeyVault.azureAccountId

Number

Azure Account ID

azureKeyVault.vaultKey

String

Vault Key

reuseKey

Boolean

Reuse key from Azure Key Vault

exportableKey

Boolean

Exportable key from Azure Key Vault (only for non HSM vaults)

hsmOnly

Boolean

HSM only key from Azure Key Vault

dcvMode

String

DCV validation mode. Possible values: [CNAME, EMAIL, HTTP, HTTPS, TXT]. Required in case of disabled DCV pre-validation.

dcvEmail

String

DCV validation email. Required in case of EMAIL DCV mode.

'Must be a well-formed email address'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/enroll-keygen' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer653' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst653' \
+    -d '{
+  "orgId" : 493,
+  "subjAltNames" : "ccmqa.com",
+  "certType" : 1132,
+  "term" : 365,
+  "comments" : "test",
+  "externalRequester" : "",
+  "customFields" : [ {
+    "name" : "custom field",
+    "value" : "custom field value"
+  } ],
+  "dcvMode" : null,
+  "dcvEmail" : null,
+  "commonName" : "ccmqa.com",
+  "keySize" : 2048,
+  "keyParam" : "2048",
+  "algorithm" : "RSA",
+  "keyGenerationMethod" : "AZURE_KEY_VAULT",
+  "azureKeyVault" : {
+    "azureAccountId" : 50,
+    "vaultKey" : "/subscriptions/dde65984-58b0-4495-bfb6-76b08f0681d7/resourceGroups/testResourceGroup/providers/Microsoft.KeyVault/vaults/name2-kv"
+  },
+  "reuseKey" : false,
+  "exportableKey" : false,
+  "hsmOnly" : false
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

renewId

String

Renew id

sslId

Number

SSL id

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 56
+
+{
+  "sslId" : 73,
+  "renewId" : "horQl1PEmas9MycxtEpb"
+}
+
+
+
+
+
+

Collect SSL certificate

+
+

Download issued SSL certificate.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/collect/{sslId}
ParameterDescription

sslId

Certificate ID.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

format

Format type for certificate. Allowed values: 'x509' - for Certificate (w/ chain), PEM encoded, 'x509CO' - for Certificate only, PEM encoded, 'base64' - for PKCS#7, PEM encoded, 'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded, 'x509IOR' - for Intermediate(s)/Root only, PEM encoded, 'pem' - for Certificate (w/ chain), PEM encoded, 'pemco' - for Certificate only, PEM encoded, 'pemia' - for Certificate (w/ issuer after), PEM encoded, 'x509R' - for Certificate (w/ chain), PEM encoded. base64 is default.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/collect/67?format=base64' -i -X GET \
+    -H 'login: admin_customer599' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst599'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/octet-stream;charset=UTF-8
+Content-Length: 7411
+Content-Disposition: attachment; filename="test.cert"
+
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFdzCCBF+gAwIBAgIQE+oocFv07O0MNmMJgGFDNjANBgkqhkiG9w0BAQwFADBv
+MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
+ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
+eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
+gYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK
+ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYD
+VQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sIs9CsVw127c0n00yt
+UINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnGvDoZtF+mvX2do2NC
+tnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQIjy8/hPwhxR79uQf
+jtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfbIWax1Jt4A8BQOujM
+8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0tyA9yn8iNK5+O2hm
+AUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97Exwzf4TKuzJM7UXiV
+Z4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNVicQNwZNUMBkTrNN9
+N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5D9kCnusSTJV882sF
+qV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJWBp/kjbmUZIO8yZ9
+HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ5lhCLkMaTLTwJUdZ
++gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzGKAgEJTm4Diup8kyX
+HAc/DVL17e8vgg8CAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTv
+A73gJMtUGjAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1Ud
+HwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4
+dGVybmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0
+dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAJNl9jeD
+lQ9ew4IcH9Z35zyKwKoJ8OkLJvHgwmp1ocd5yblSYMgpEg7wrQPWCcR23+WmgZWn
+RtqCV6mVksW2jwMibDN3wXsyF24HzloUQToFJBv2FAY7qCUkDrvMKnXduXBBP3zQ
+YzYhBx9G/2CkkeFnvN4ffhkUyWNnkepnB2u0j4vAbkN9w6GAbLIevFOFfdyQoaS8
+Le9Gclc1Bb+7RrtubTeZtv8jkpHGbkD4jylW6l/VXxRTrPBPYer3IsynVgviuDQf
+Jtl7GQVoP7o81DgGotPmjw7jtHFtQELFhLRAlSv0ZaBIefYdgWOWnU914Ph85I6p
+0fKtirOMxyHNwu8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIF9TCCA92gAwIBAgIQHaJIMG+bJhjQguCWfTPTajANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
+MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjB8MQswCQYDVQQGEwJHQjEbMBkGA1UE
+CBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQK
+Ew9TZWN0aWdvIExpbWl0ZWQxJDAiBgNVBAMTG1NlY3RpZ28gUlNBIENvZGUgU2ln
+bmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIYijTKFehif
+SfCWL2MIHi3cfJ8Uz+MmtiVmKUCGVEZ0MWLFEO2yhyemmcuVMMBW9aR1xqkOUGKl
+UZEQauBLYq798PgYrKf/7i4zIPoMGYmobHutAMNhodxpZW0fbieW15dRhqb0J+V8
+aouVHltg1X7XFpKcAC9o95ftanK+ODtj3o+/bkxBXRIgCFnoOc2P0tbPBrRXBbZO
+oT5Xax+YvMRi1hsLjcdmG0qfnYHEckC14l/vC0X/o84Xpi1VsLewvFRqnbyNVlPG
+8Lp5UEks9wO5/i9lNfIi6iwHr0bZ+UYc3Ix8cSjz/qfGFN1VkW6KEQ3fBiSVfQ+n
+oXw62oY1YdMCAwEAAaOCAWQwggFgMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvA
+nfKyA2bLMB0GA1UdDgQWBBQO4TqoUzox1Yq+wbutZxoDha00DjAOBgNVHQ8BAf8E
+BAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEFBQcDAwYI
+KwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMFAGA1UdHwRJMEcwRaBDoEGGP2h0
+dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6
+Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAl
+BggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0B
+AQwFAAOCAgEATWNQ7Uc0SmGk295qKoyb8QAAHh1iezrXMsL2s+Bjs/thAIiaG20Q
+BwRPvrjqiXgi6w9G7PNGXkBGiRL0C3danCpBOvzW9Ovn9xWVM8Ohgyi33i/klPeF
+M4MtSkBIv5rCT0qxjyT0s4E307dksKYjalloUkJf/wTr4XRleQj1qZPea3FAmZa6
+ePG5yOLDCBaxq2NayBWAbXReSnV+pbjDbLXP30p5h1zHQE1jNfYw08+1Cg4LBH+g
+S667o6XQhACTPlNdNKUANWlsvp8gJRANGftQkGG+OY96jk32nw4e/gdREmaDJhlI
+lc5KycF/8zoFm/lv34h/wCOe0h5DekUxwZxNqfBZslkZ6GqNKQQCd3xLS81wvjqy
+VVp4Pry7bwMQJXcVNIr5NsxDkuS6T/FikyglVyn7URnHoSVAaoRXxrKdsbwcCtp8
+Z359LukoTBh+xHsxQXGaSynsCz1XUNLK3f2eBVHlRHjdAd6xdZgNVCT98E7j4viD
+vXK6yz067vBeF5Jobchh+abxKgoLpbn0nu6YMgWFnuv5gynTxix9vTp3Los3QqBq
+gu07SqqUEKThDfgXxbZaeTMYkuO1dfih6Y4KJR7kHvGfWocj/5+kUZ77OYARzdu1
+xKeogG/lU9Tg46LC0lsa+jImLWpXcBw8pFguo/NbSwfcMlnzh6cabVg=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFCjCCA/KgAwIBAgIRAKicluNCIKrVY1IbC+37vhUwDQYJKoZIhvcNAQELBQAw
+fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD
+ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTkwNjEzMDAwMDAwWhcN
+MjEwNjEyMjM1OTU5WjB7MQswCQYDVQQGEwJDQTEOMAwGA1UEEQwFNTU1MjYxDjAM
+BgNVBAgMBUlkYWhvMQ8wDQYDVQQHDAZLYW5hdGExEzARBgNVBAkMCjE5ODggbWFy
+Y2gxEjAQBgNVBAoMCXRlc3QgY3JvcDESMBAGA1UEAwwJdGVzdCBjcm9wMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6A5w8ndXAWk8+6Zx+84FRiIX+B6t
+xiKp1MHk7YA90mUdoU6nX/nqZErAtLMCr3C8x1nDlKZRvpMQIZhAT30orTm2TQXE
+jOD5zIpxgG0YtQEyGRcpdehviwl+IkdWltgZe4adghJKUWEKfCvnWJrnK81ppcuA
+xla4A1uLXYV7PoZIDi527xZK12SC9hxKYOHlcJ/od+NsUv114KFUTGe/EGuV9TQj
+/VBOeObbfeAoOJvDNSso5EXKOu/WtEdiDZ5+2oUFz4lyzQyTtUA4cikClOfd2xBD
+DvmfuoPhPj+1UsdqSDbE5xS3O8eIU9rnzVAbWe7YKe7+UBq8Sg2HUqJm2QIDAQAB
+o4IBhjCCAYIwHwYDVR0jBBgwFoAUDuE6qFM6MdWKvsG7rWcaA4WtNA4wHQYDVR0O
+BBYEFNpOBbcvZE5tFiSfOs1nwjjWXWtIMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
+Af8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBA
+BgNVHSAEOTA3MDUGDCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczov
+L3NlY3RpZ28uY29tL0NQUzBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnNl
+Y3RpZ28uY29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEFBQcB
+AQRnMGUwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGln
+b1JTQUNvZGVTaWduaW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5z
+ZWN0aWdvLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAAAECAwQFBgcICQoLDA0ODxAR
+EhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BB
+QkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch
+oqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR
+0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
+-----END CERTIFICATE-----
+
+
+
+
+
+

Download private key from Private Key Agent

+
+

Generation of a link to download private key from Private Key Agent.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/ssl/v1/keystore/{sslId}/{formatType}
ParameterDescription

sslId

SSL ID for which the link will be generated.

formatType

Parameter to specify download format: key only or entire certificate. Possible values: 'key' - for Private Key, Base64 encoded, +'p12' - for PKCS#12, Base64 encoded, +'p12aes' - for Certificate and Private Key, PKCS#12, +'jks' - for Certificate and Private Key, Java Key Store, +'pem' - for Certificate and Private Key, Encrypted PEM,

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

passphrase

String

Passphrase to protect certificate with private key.

Must comply to organization password policy. [Maximum length is 32 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/keystore/138/p12' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer971' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst971' \
+    -H 'Accept: application/json' \
+    -d '{
+  "passphrase" : "123"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 110
+
+{
+  "link" : "https://{private_key_agent_host_name}/download?token=9STOEPH57C84UOME35RFR165QI&keyformat=p12"
+}
+
+
+
+
+
+

Approve SSL certificate

+
+

Approve a SSL certificate request that needs approval.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/approve/{sslId}
ParameterDescription

sslId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

message

String

Short message containing accompanying information for certificate approval action

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/approve/90' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer819' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst819' \
+    -d '{
+  "message" : "test"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Decline SSL certificate

+
+

Decline a SSL certificate request.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/decline/{sslId}
ParameterDescription

sslId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

message

String

Short message containing accompanying information for certificate declining action

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/decline/134' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer925' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst925' \
+    -d '{
+  "message" : "test"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Manage SSL certificate

+
+

Update SSL certificate details

+
+

Update SSL certificate.

+
+
+ + + + + +
+ + +You can update only certificate fields listed in the table below. Organization ID, Certificate Profile ID, Term, Common name, CSR, SANs can be edited if a certificate state is one of: Requested, Declined, Rejected, Invalid +
+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

sslId

Number

Certificate ID

[Must be at least 1, Must not be null]

term

Number

Term (days)

[Must be at least 1]

certTypeId

Number

Certificate Profile ID

[Must be at least 1]

orgId

Number

Organization ID

[Must be at least 1]

commonName

String

Certificate common name

[]

csr

String

Certificate signing request

[Must match the regular expression [a-zA-Z0-9-=\/\s], Size must be between 1 and 32767 inclusive]

externalRequester

String

External requester emails, comma-separated

[]

comments

String

Comments

[Maximum length is 1024 characters or can be empty]

subjectAlternativeNames

Array

Subject alternative names

[]

customFields

Array

Custom fields

[]

customFields[].name

String

Example of custom field name

[Must not be null, Size must be between 1 and 256 inclusive]

customFields[].value

String

Example of custom field value. For input type 'DATE' format is yyyy-MM-dd

[Must not be null, Maximum length is 256 characters or can be empty]

autoRenewDetails

Object

Auto-Renewal Information

[]

autoRenewDetails.state

String

Auto-Renewal state

[Allowed values 'Not scheduled' and 'Scheduled'], defaults to 'Not scheduled'

autoRenewDetails.daysBeforeExpiration

Number

Days before expiration to start auto-renewal

[Must be at least 1], defaults to 30 days. Auto-renewal state must be 'Scheduled' for days to update

suspendNotifications

Boolean

Suspend Notifications for the certificate

[]

requester

String

Requester

[]

requesterAdminId

Number

Requester Admin Id

[Must be at least 1]

approverAdminId

Number

Approver Admin Id. Value -1 will set the approver admin to <None>

[Must be at least -1]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1294' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1294' \
+    -H 'Accept: application/json' \
+    -d '{
+  "customFields" : [ {
+    "name" : "name1",
+    "value" : "value1"
+  } ],
+  "comments" : "some comments",
+  "sslId" : 176,
+  "term" : 365,
+  "certTypeId" : 1200,
+  "orgId" : 732,
+  "commonName" : "ccmqa.com",
+  "csr" : "MIIC1zCCAb8CAQAwgZExCzAJBgNVBAYTAlVBMRIwEAYDVQQIDAljY21xYS5jb20x\nEjAQBgNVBAcMCWNjbXFhLmNvbTESMBAGA1UECgwJY2NtcWEuY29tMRIwEAYDVQQL\nDAljY21xYS5jb20xEjAQBgNVBAMMCWNjbXFhLmNvbTEeMBwGCSqGSIb3DQEJARYP\nYWRtaW5AY2NtcWEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\nsdkqSb/r4zpbi2GCnCRvYo+CbnQg/wRbsObr0m9OXEP1jSTuj8CqJZvTnGjE15fy\npdTGadc40saepghV4gIUOnFpYQRZacSN3VPLxF9rjnLEDBn7mTqbtbvxjhOaiPYz\nZgEa6kOOf851rujvl0WClMuWTIoXM7OmaHZA1NorGc3lag+D+4Tx8j1ry22EphXE\nd+Pm+4Tf/Fshd9Cm1r1JLcnlq0YdkV6ynzeKbUJX1cdYyMrxWTnBy/Tp0dM8FDGY\nMQ3ArQBIaDPGOnq1Gfd/yLrbaQD/j0ntZ4WKIWTlJLAkDu0AySz9Tc+DBCTrGvor\n9tjfWaeQo7CU+pENRyYzEwIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAIBptH2V\nU66GWFt5nHiMZnPRD8r4/JfqDvtPbV+qbXz2G/S+nuw0dhzGb4zCp6INH7UgO21o\nGHqIO2we9o31CmfbfJBptQdcJ0h+b/1Awp/DJulwoNXHgUqq+PbKe2j+QdOTH8EG\nszGnRo3Li9WA+V3LkYi0GkBFKsP5SyKFA/am2A0TRyy9FJ6MaMPkwV397tKJJ+Hu\n0/YfJkwTaK6JGujEQOUBtTU6QmpWjfih5CafxaDFrFkzdPo8by+W8W13T1dvqBcs\nAZtdcEIcajHZ6sF/xEm9Dfui17R8a4kAHx8QD046mEt0/OxAacEURKkJeRQlRgN9\nTSfJ16hdPk69U4M=",
+  "externalRequester" : "",
+  "subjectAlternativeNames" : [ "ccmqa.com" ]
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

sslId

Number

An ID using which this certificate can be renewed or revoked through Enrollment form. Deprecated. Use 'id' instead

id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

orderNumber

Number

The obsolete parameter for the order identifier under which the certificate request has been processed. backendCertId should be used instead

backendCertId

String

Certificate ID in enrolling backend

vendor

String

The name of the issuing CA

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

subType

String

SSL Subtype, available only for managed certificates. Deprecated, will be removed in favor of validationType

validationType

String

Validation type, available only for managed certificates

term

Number

Term (days)

owner

String

The approver of the request for this certificate

ownerId

Number

The approver ID of the request for this certificate

requester

String

Requester

requesterId

Number

The Requester ID, when available

requestedVia

String

Requested Via. Possible values: 'Enrollment Form', 'Client Admin', 'Web API', 'Discovery', 'Imported', 'SCEP', 'CD Agent', 'MS Agent', 'MS CA', 'Bulk Request', 'ACME', 'EST', 'REST API'

externalRequester

String

External Requester, when available

comments

String

Comments

requested

String

Requested date

approved

String

Approved date

issued

String

Issued date

declined

String

Declined date

expires

String

Expiration date

replaced

String

Replaced date

revoked

String

Revocation date

reasonCode

Number

Revocation reason code provided on revoke to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

renewed

Boolean

Renewal indicator

renewedDate

String

Renewal date

signatureAlg

String

Signature Algorithm

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

keyUsages

Array

Key Usages

extendedKeyUsages

Array

Extended Key Usages

subjectAlternativeNames

Array

Subject alternative names

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value. For input type 'DATE' format is yyyy-MM-dd

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

autoInstallDetails

Object

Auto-Installation Information

autoInstallDetails.state

String

Auto-Installation state

autoInstallDetails.nodes[]

Array

Auto-Installation nodes (planned or already installed to)

autoInstallDetails.nodes[].name

String

Node name

autoInstallDetails.nodes[].port

Number

Node port

autoRenewDetails

Object

Auto-Renewal Information

autoRenewDetails.state

String

Auto-Renewal state

autoRenewDetails.daysBeforeExpiration

Number

Days before expiration to start auto-renewal

suspendNotifications

Boolean

Suspend Notifications for the certificate

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 1198
+
+{
+  "commonName" : "ccmqa.com",
+  "sslId" : 176,
+  "id" : 176,
+  "orgId" : 732,
+  "status" : "Requested",
+  "orderNumber" : 7344326,
+  "backendCertId" : "7344326",
+  "vendor" : "Vendor",
+  "certType" : {
+    "id" : 1200,
+    "name" : "SSL SASP -1212434397",
+    "description" : "SSL SASP -1577387451",
+    "terms" : [ 365 ],
+    "keyTypes" : {
+      "RSA" : [ "1024", "2048", "4096" ]
+    },
+    "useSecondaryOrgName" : false
+  },
+  "validationType" : "Organization Validation (OV)",
+  "term" : 365,
+  "owner" : "client-admin-1299 client-admin-1299",
+  "ownerId" : 557,
+  "requester" : "1297_nobody@nobody.sectigo.com",
+  "requestedVia" : "Enrollment Form",
+  "comments" : "some comments",
+  "requested" : "08/15/2025",
+  "expires" : "08/15/2026",
+  "renewed" : false,
+  "keyAlgorithm" : "RSA",
+  "keySize" : 0,
+  "keyType" : "RSA",
+  "subjectAlternativeNames" : [ "ccmqa.com" ],
+  "customFields" : [ {
+    "name" : "name1",
+    "value" : "value1"
+  } ],
+  "certificateDetails" : {
+    "issuer" : "issuer",
+    "sha1Hash" : "AAABBBCCC"
+  },
+  "autoInstallDetails" : {
+    "state" : "Not configured"
+  },
+  "autoRenewDetails" : {
+    "state" : "Not scheduled"
+  },
+  "suspendNotifications" : false
+}
+
+
+
+
+
+

Revoke SSL certificate by Id

+
+

Sending a request to CA to add the particular SSL certificate in certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/revoke/{sslId}
ParameterDescription

sslId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message with a reason why certificate needs to be revoked

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/revoke/167' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1210' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1210' \
+    -d '{
+  "reasonCode" : 4,
+  "reason" : "my reason"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Revoke SSL certificate by serial number

+
+

Sending a request to CA to add the particular SSL certificate in certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/revoke/serial/{serialNumber}
ParameterDescription

serialNumber

Serial Number of certificate

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message with a reason why certificate needs to be revoked

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/revoke/serial/A9:3E:C0:61:FB:1E:C0:10:73:05:65:00:8D:72:D8:69' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1254' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1254' \
+    -d '{
+  "reasonCode" : 3,
+  "reason" : "my reason"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Manual Revoke SSL certificate by Id or serial number + issuer

+
+

Mark certificate as revoked. The certificate is not revoked on CA side.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

certId

Number

Certificate ID. Required if serialNumber and issuer are not provided.

Must be present if serialNumber and issuer are not provided

serialNumber

Number

Certificate serial number. Required if certId is not provided (used together with issuer).

Must be present with issuer if certId is not provided

issuer

Number

Certificate issuer. Required if certId is not provided (used together with serialNumber).

Must be present with serialNumber if certId is not provided

revokeDate

String

Certificate revoke date

[]

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/revoke/manual' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1160' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1160' \
+    -d '{
+  "certId" : 163,
+  "serialNumber" : null,
+  "issuer" : null,
+  "revokeDate" : "2025-06-10T00:00:00Z",
+  "reasonCode" : 4
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Renew SSL certificate by renew Id

+
+

Submission of a request for a new SSL certificate using the CSR and parameters of the initial certificate. The initial certificate is the one that is selected by the administrator for renewal in this case.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/renew/{renewId}
ParameterDescription

renewId

Renew ID for certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

csr

String

Certificate signing request (optional)

'Must match the regular expression [a-zA-Z0-9-=\/\s],Size must be between 1 and 32767 inclusive'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/renew/10' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer783' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst783' \
+    -d '{
+  "csr" : "-----BEGIN CERTIFICATE REQUEST-----\nMIICyTCCAbECAQAwgYMxCzAJBgNVBAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzAN\nBgNVBAcMBk9kZXNzYTERMA8GA1UECgwIQWR2YW5jZWQxCzAJBgNVBAsMAklUMRIw\nEAYDVQQDDAljY21xYS5jb20xHjAcBgkqhkiG9w0BCQEWD25teXphQGNjbXFhLmNv\nbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMHZo0lPzCqBVu03qHJa\np2wbOyN8kvdkU2VRj+GaF2APgrQps/sepvhyralxa9w5WD5KyoXhnM+7DPCsqDxK\nkxsBjEliLQqXwmoiai0A2DMmjWCoSMopzNTIORLPn8GaWFJSEtCa+9D1EXD2UZjS\nY/8MN0fEAIqaXFUrfW3cqW/QUjZH0mlJumUqQjtZY0DnAQsCxxZUlsHCkKEHuEQu\n5WhY8ys1/RANaoJmRh2xZuFMOZ71kLkwi5fvReqxjkRRHwG9cYDyurTNYmjkaICN\n/hqUwk9VKkW0G5ol8t0xau8RuHdDHi5Wb/R6+d/G+8/kn0BoOqseABih1+FYs+Ws\nK8UCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQA15aWRLayIuUZmPhdrpJXQAtrw\nAoeYYwp5hvaTLwZBWEg5n+ZhH5SaSCpt+53QW3+jiT8jTsPKAqyvgSQI0MVi8o5J\nJhig6pPHGSKbfxmvmfSwxK4F9W2GNVcdICX+Js0BB5UXsZB4k1gTRr1VdICNiCDc\nDZAC0+HhkZSU9StD43T9ac3gZIfEEepX9WBx9QbBASbUZ1ziSBfGKA7vnQHbC9lT\nphLa2SvCSozmG36vYMV+Ak5YWnrp2c1Jhcd8PE0TIW6yPT+D6UvcZWb+KHfw2KAH\nVXPNFSgSZkMzFBMQJH9UcfyvPX5+7qXakxAhLS/zKOg7Y601cRg5/Eqa0Z59\n-----END CERTIFICATE REQUEST-----\n"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Renew SSL certificate by Id

+
+

Submission of a request for a new SSL certificate using the CSR and parameters of the initial SSL certificate. The initial certificate is defined by its ID in this case.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/renewById/{sslId}
ParameterDescription

sslId

Certificate ID.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

csr

String

Certificate signing request (optional)

'Must match the regular expression [a-zA-Z0-9-=\/\s],Size must be between 1 and 32767 inclusive'

dcvMode

String

Domain control validation mode. Possible values: [CNAME, EMAIL, HTTP, HTTPS, TXT]

dcvEmail

String

Domain control validation email

'Must be a well-formed email address'

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/renewById/75' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer721' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst721' \
+    -d '{
+  "csr" : "-----BEGIN CERTIFICATE REQUEST-----\nMIICyTCCAbECAQAwgYMxCzAJBgNVBAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzAN\nBgNVBAcMBk9kZXNzYTERMA8GA1UECgwIQWR2YW5jZWQxCzAJBgNVBAsMAklUMRIw\nEAYDVQQDDAljY21xYS5jb20xHjAcBgkqhkiG9w0BCQEWD25teXphQGNjbXFhLmNv\nbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMHZo0lPzCqBVu03qHJa\np2wbOyN8kvdkU2VRj+GaF2APgrQps/sepvhyralxa9w5WD5KyoXhnM+7DPCsqDxK\nkxsBjEliLQqXwmoiai0A2DMmjWCoSMopzNTIORLPn8GaWFJSEtCa+9D1EXD2UZjS\nY/8MN0fEAIqaXFUrfW3cqW/QUjZH0mlJumUqQjtZY0DnAQsCxxZUlsHCkKEHuEQu\n5WhY8ys1/RANaoJmRh2xZuFMOZ71kLkwi5fvReqxjkRRHwG9cYDyurTNYmjkaICN\n/hqUwk9VKkW0G5ol8t0xau8RuHdDHi5Wb/R6+d/G+8/kn0BoOqseABih1+FYs+Ws\nK8UCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQA15aWRLayIuUZmPhdrpJXQAtrw\nAoeYYwp5hvaTLwZBWEg5n+ZhH5SaSCpt+53QW3+jiT8jTsPKAqyvgSQI0MVi8o5J\nJhig6pPHGSKbfxmvmfSwxK4F9W2GNVcdICX+Js0BB5UXsZB4k1gTRr1VdICNiCDc\nDZAC0+HhkZSU9StD43T9ac3gZIfEEepX9WBx9QbBASbUZ1ziSBfGKA7vnQHbC9lT\nphLa2SvCSozmG36vYMV+Ak5YWnrp2c1Jhcd8PE0TIW6yPT+D6UvcZWb+KHfw2KAH\nVXPNFSgSZkMzFBMQJH9UcfyvPX5+7qXakxAhLS/zKOg7Y601cRg5/Eqa0Z59\n-----END CERTIFICATE REQUEST-----\n",
+  "dcvMode" : "EMAIL",
+  "dcvEmail" : "admin@ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

sslId

Number

New certificate ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 18
+
+{
+  "sslId" : 76
+}
+
+
+
+
+
+

Mark Renewed SSL certificate

+
+

Manually marking an SSL certificate as renewed, optionally linking it to a new certificate ID or Order Number. The initial certificate is defined by its ID.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/renew/manual/{sslId}
ParameterDescription

sslId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

id

Number

Renewed certificate ID (optional)

orderNumber

String

Renewed certificate Order Number (optional)

dcvMode

String

DCV validation mode. Possible values: [CNAME, EMAIL, HTTP, HTTPS, TXT]

dcvEmail

String

DCV validation email. Required in case of EMAIL DCV mode.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/renew/manual/77' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer729' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst729' \
+    -d '{
+  "id" : 78,
+  "dcvMode" : "EMAIL",
+  "dcvEmail" : "admin@ccmqa.com"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Replace SSL certificate by Id

+
+

Submission of a request for the substition of the particular SSL certificate applying its parameters and a new CSR.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/replace/{sslId}
ParameterDescription

sslId

Certificate ID.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

csr

String

Certificate signing request

[Must match the regular expression [a-zA-Z0-9-=\/\s], Must not be empty, Size must be between 1 and 32767 inclusive]

reason

String

Short message with a reason why certificate needs to be replaced

[Must not be empty, Size must be between 1 and 512 inclusive]

commonName

String

Certificate common name

[Size must be between 1 and 64 inclusive]

subjectAlternativeNames

Array

Array of subject alternative names

[]

dcvMode

String

Domain control validation mode. Possible values: [CNAME, EMAIL, HTTP, HTTPS, TXT]

[]

dcvEmail

String

Domain control validation email

[Must be a well-formed email address]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/replace/89' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer799' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst799' \
+    -d '{
+  "csr" : "-----BEGIN CERTIFICATE REQUEST-----\nMIICyTCCAbECAQAwgYMxCzAJBgNVBAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzAN\nBgNVBAcMBk9kZXNzYTERMA8GA1UECgwIQWR2YW5jZWQxCzAJBgNVBAsMAklUMRIw\nEAYDVQQDDAljY21xYS5jb20xHjAcBgkqhkiG9w0BCQEWD25teXphQGNjbXFhLmNv\nbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMHZo0lPzCqBVu03qHJa\np2wbOyN8kvdkU2VRj+GaF2APgrQps/sepvhyralxa9w5WD5KyoXhnM+7DPCsqDxK\nkxsBjEliLQqXwmoiai0A2DMmjWCoSMopzNTIORLPn8GaWFJSEtCa+9D1EXD2UZjS\nY/8MN0fEAIqaXFUrfW3cqW/QUjZH0mlJumUqQjtZY0DnAQsCxxZUlsHCkKEHuEQu\n5WhY8ys1/RANaoJmRh2xZuFMOZ71kLkwi5fvReqxjkRRHwG9cYDyurTNYmjkaICN\n/hqUwk9VKkW0G5ol8t0xau8RuHdDHi5Wb/R6+d/G+8/kn0BoOqseABih1+FYs+Ws\nK8UCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQA15aWRLayIuUZmPhdrpJXQAtrw\nAoeYYwp5hvaTLwZBWEg5n+ZhH5SaSCpt+53QW3+jiT8jTsPKAqyvgSQI0MVi8o5J\nJhig6pPHGSKbfxmvmfSwxK4F9W2GNVcdICX+Js0BB5UXsZB4k1gTRr1VdICNiCDc\nDZAC0+HhkZSU9StD43T9ac3gZIfEEepX9WBx9QbBASbUZ1ziSBfGKA7vnQHbC9lT\nphLa2SvCSozmG36vYMV+Ak5YWnrp2c1Jhcd8PE0TIW6yPT+D6UvcZWb+KHfw2KAH\nVXPNFSgSZkMzFBMQJH9UcfyvPX5+7qXakxAhLS/zKOg7Y601cRg5/Eqa0Z59\n-----END CERTIFICATE REQUEST-----\n",
+  "reason" : "test",
+  "commonName" : "ccmqa.com",
+  "subjectAlternativeNames" : [ "ccmqa1.com", "ccmqa2.com" ],
+  "dcvMode" : "EMAIL",
+  "dcvEmail" : "admin@ccmqa.com"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete SSL certificate by Id

+
+

Submission of a request for deleting SSL certificate for a given SSL Id.

+
+
+ + + + + +
+ + +Only imported or discovered certificates can be deleted. +
+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/ssl/v1/{sslId}
ParameterDescription

sslId

Certificate ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/70' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer623' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst623'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Import SSL certificates to SCM

+
+

Import certificates to SCM

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

orgId

An organization which this certificates import to

+
+
+
Request parts
+ ++++ + + + + + + + + + + + + +
PartDescription

file

Zip archive with certificates to import

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v1/import?orgId=638' -i -X POST \
+    -H 'Content-Type: multipart/form-data;charset=UTF-8' \
+    -H 'login: admin_customer1034' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1034' \
+    -F 'file=@certs.zip;type=application/zip'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

errors

Array

An array of occurred errors

processedCount

Number

Total number of processed certificates

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 426
+
+{
+  "processedCount" : 8,
+  "errors" : [ "[appov_ccmqa_com_cert.cer] - SSL certificate already exists. Order number: N/A", "[ccmqa_com.crt] - SSL certificate already exists. Order number: N/A", "admin_ccmqa_com.p12 - Unsupported file extension", "appov_ccmqa_com_interm.cer - Failed to parse certificate: Certificate is corrupted or subject basic constraint is not met", "auto83_ccmqa_com.p12 - Unsupported file extension" ]
+}
+
+
+
+
+
+

Import SSL certificates to SCM (extended)

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

[]

Array

Certificates to import

Should not be empty, maximum size is 128

[].orgID

Number

Organization ID

[Must be at least 1, Must not be null]

[].customFields

Array

List of custom certificate fields

[]

[].customFields[].name

String

Custom field name

[]

[].customFields[].value

String

Custom field value

[]

[].owner

String

Certificate owner

[Must be a well-formed email address, Maximum length is 128 characters or can be empty]

[].externalRequester

String

Comma-separated additional emails

[Maximum length is 512 characters or can be empty]

[].backendCertId

String

Backend certificate identifier

[Maximum length is 255 characters or can be empty]

[].cert

String

DER (Base64) certificate

[Must not be empty]

[].csr

String

DER (Base64) Certificate Signing Request

[]

[].comments

String

Additional comments

[Maximum length is 1024 characters or can be empty]

[].force

Boolean

Force alter editable certificate fields event if certificate is already exists.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/ssl/v2/import' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1319' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1319' \
+    -d '[{"orgID":739,"customFields":[{"name":"testName","value":"testValue"}],"owner":"admin@requester.com","externalRequester":"email@one.com, email@two.com","backendCertId":"1234567890DFa","cert":"MIIHHjCCBgagAwIBAgIQDhG71w1UtxDQxvVAtrUspDANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xNjA1MjEwMDAwMDBaFw0xOTA4MTQxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJOWTERMA8GA1UEBxMITmV3IFlvcmsxHTAbBgNVBAoTFFN0YWNrIEV4Y2hhbmdlLCBJbmMuMRwwGgYDVQQDDBMqLnN0YWNrZXhjaGFuZ2UuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr0YDzscT5i6T2FaRsTGNCiLB8OtPXu8N9iAyuaROh/nS0kRRsN8wUMk1TmgZhPuYM6oFS377V8W2LqhLBMrPXi7lnhvKt2DFWCyw38RrDbEsM5dzVGErmhux3F0QqcTI92zjVW61DmE7NSQLiR4yonVpTpdAaO4jSPJxn8d+4p1sIlU2JGSk8LZSWFqaROc7KtXtlWP4HahNRZtdwvL5dIEGGNWx+7B+XVAfY1ygc/UisldkA+a3D2+3WAtXgFZRZZ/1CWFjKWJNMAI6ZBAtlbgSNgRYxdcdleIhPLCzkzWysfltfiBmsmgz6VCoFR4KgJo8Gd3MeTWojBthM10SLwIDAQABo4IDuDCCA7QwHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFFrBQmPCYhOznZSEqjIeF8tto4Z7MIIB6AYDVR0RBIIB3zCCAduCEyouc3RhY2tleGNoYW5nZS5jb22CEXN0YWNrb3ZlcmZsb3cuY29tghMqLnN0YWNrb3ZlcmZsb3cuY29tgg1zdGFja2F1dGguY29tggtzc3RhdGljLm5ldIINKi5zc3RhdGljLm5ldIIPc2VydmVyZmF1bHQuY29tghEqLnNlcnZlcmZhdWx0LmNvbYINc3VwZXJ1c2VyLmNvbYIPKi5zdXBlcnVzZXIuY29tgg1zdGFja2FwcHMuY29tghRvcGVuaWQuc3RhY2thdXRoLmNvbYIRc3RhY2tleGNoYW5nZS5jb22CGCoubWV0YS5zdGFja2V4Y2hhbmdlLmNvbYIWbWV0YS5zdGFja2V4Y2hhbmdlLmNvbYIQbWF0aG92ZXJmbG93Lm5ldIISKi5tYXRob3ZlcmZsb3cubmV0gg1hc2t1YnVudHUuY29tgg8qLmFza3VidW50dS5jb22CEXN0YWNrc25pcHBldHMubmV0ghIqLmJsb2dvdmVyZmxvdy5jb22CEGJsb2dvdmVyZmxvdy5jb22CGCoubWV0YS5zdGFja292ZXJmbG93LmNvbYIVKi5zdGFja292ZXJmbG93LmVtYWlsghNzdGFja292ZXJmbG93LmVtYWlsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc1LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc1LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAAzJAMGSdKoX1frdqNlNiXu8Gcbsm/DxWMXpcTXlZn8s+/qQQoc+/3o0CK3C8/j9n5DmsYa88P6Ntt5ysDs+b0ynXFva4CAEyKaoPM4SIpOjwfWBRSUOqAIkQO2/LhKBwT/EnpaIHIKGnI0UdXLQoDfkMDg6mgJsEBsKdKF5EfEX7iU3NO5xVJPJE8/R0btLAdYwxB9S6fSpCXGe2HqQD101O/7/4MWNdFSbfdDSFcn5oEm+idimrqiNrF5knmuJy4qPBkL7thNuGK6rvYCFZJM03ZEZhkQmn2jG/7LgjfwZmvfcITeADCpylf88bL+lf+vxe6cCl9CyqWgBDpsIxpE=","csr":"MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCY24xDzANBgNVBAgTBmJlaWppbjEQMA4GA1UEBxMHYmVpamluZzEPMA0GA1UEChMGQ09NT0RPMRAwDgYDVQQLEwdkZXZlbG9wMREwDwYDVQQDDAgqLmNtLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxrVE6cqSTe+jOsyYjBNw+5uZeDdu37bRgw6qQo2uSFhOhXyhsxcb0zaitpjNYLsEc4fp0YzNYrqzmIHK7HpgHgg9N9CVr0m2O/RlV761s257expajU1vYzVDIt/levLkOJe96++tOFOQ+6hrFnI2YWKxLdE+X0F7tGrDgkV2xXhW7qbw32C2kRyui3KvgoJ0Mwtwe0Gp6VVN61oNoinf5F/O8MGMFmM4TaRgSTcvWIJvrfuMTmHi9S918LfQRrFGfDKNX49iS8oWT7SVBmLxjcEqIsTfCFo9rg/aP8elS3kRFBH8fTNUPjcOCa/Km6JoIM4C/KEro6uraXAbl+QhMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQBvyheU7vn+VCQJz8OHVD2r9c79KETEeaTMIvnTjGECd3RlXXErcFxuvFJYtTyiNZwzyRi7Q4IBp8g41UYRsBsMim0ioQdW9cIIMMn0oY7oAuQt6eM77iOd/bWhpGAPKe6rG8vadA6nF+hPIPEkqIlfWYNc/ZarvXr2UPNmYdv/skDi9PQUlzB1xOWQUO3Li+QYZWuE3UjLDNCoh5uTY5UMn/K+Ej8fDDz4mc4zZQQf3mASZcMEv75pqfEiRY1zUUPLLT5vUZ5yh32DG8mm+X5Gkr1xQNYGAUymxTdG2ct2t3xxLjGmRABxPvGNIrIefboyLma9Yd0GBOtrexsNzbUI","comments":"Test comments","force":true}]'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of certificates

[].cert

Object

SSL information

[].cert.id

Number

SSL ID

[].cert.subject

String

SSL Subject

[].cert.serialNumber

String

SSL Serial Number

[].created

Boolean

Whether certificate been created or not (it could already exist)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 165
+
+[{"cert":{"id":179,"subject":"CN=*.stackexchange.com,O=Stack Exchange, Inc.,L=New York,ST=NY,C=US","serialNumber":"E11BBD70D54B710D0C6F540B6B52CA4"},"created":true}]
+
+
+
+
+

The response array element can be error message:

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[].errorMessage

String

Error message

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 59
+
+[{"errorMessage":"Custom field cannot be found: testName"}]
+
+
+
+
+
+
+
+
+

Client Certificates

+
+
+

Used to perform operations on client certificates.

+
+
+

Client certificate helper APIs

+
+

List client certificate profiles

+
+

List client certificate profiles, previously known as a certificate type. An enrollment request will require the certificate profile be specified.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

organizationId

Filter by Organization ID (optional)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/types?organizationId=3151' -i -X GET \
+    -H 'login: admin_customer21360' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21360' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of available Client Certificate Profiles

[].id

Number

Certificate Profile ID

[].name

String

Certificate Profile name

[].useSecondaryOrgName

Boolean

Use secondary organization name

[].description

String

Certificate Profile description

[].terms

Array

Terms (in days) available for the Certificate Profile

[].keyTypes

Object

Key types available for the Certificate Profile

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 179
+
+[{"id":2028,"name":"Client cert SASP -1595985077","description":"Client cert SASP 1296632389","terms":[365],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false}]
+
+
+
+
+
+

List client certificate custom fields

+
+

List client certificate custom fields. An enrollment require will require all mandatory custom fields be specified.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/customFields' -i -X GET \
+    -H 'login: admin_customer21322' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21322' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of custom fields

[].id

Number

Custom field id

[].name

String

Custom field name

[].mandatory

Boolean

Is field mandatory

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 47
+
+[{"id":156,"name":"testName","mandatory":true}]
+
+
+
+
+
+
+

Client certificate locations

+
+

List client certificate locations

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/{certId}/location
ParameterDescription

certId

Certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/126/location' -i -X GET \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21238' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21238'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Client Certificate Locations

[].id

Number

Location ID

[].locationType

String

Location Type

[].name

String

Location Name (optional)

[].details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 150
+
+[{"id":84,"locationType":"CUSTOM","name":"","details":{"location1":"PC"}},{"id":85,"locationType":"CUSTOM","name":"","details":{"location2":"Phone"}}]
+
+
+
+
+
+

Create custom location for client certificate

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/{certId}/location
ParameterDescription

certId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/123/location' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21201' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21201' \
+    -d '{"details":{"location":"Tablet"}}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of the created certificate location entity

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/smime/v2/123/location/81
+
+
+
+
+
+

Get details of client certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/smime/v2/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/125/location/83' -i -X GET \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21229' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21229'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Location ID

locationType

String

Location Type

name

String

Location Name (optional)

details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 79
+
+{"id":83,"locationType":"CUSTOM","name":"","details":{"Mail Client":"Outlook"}}
+
+
+
+
+
+

Update client certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/smime/v2/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/135/location/86' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21277' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21277' \
+    -d '{"details":{"MailClient":"Thunderbird"}}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete client certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/smime/v2/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/124/location/82' -i -X DELETE \
+    -H 'login: admin_customer21208' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21208'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

View client certificates

+
+

List client certificates

+
+

List all client certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

keyVault

Filter by certificate Key Vault flag

personId

Filter by certificate person ID

state

Filter by certificate state. Possible values: ', 'blank', 'created', 'requested', 'issued', 'downloaded' - deprecated, 'expired', 'revoked', 'rejected', 'pre_revoked''

certTypeId

Filter by certificate profile ID

serialNumber

Filter by certificate serial number

backendCertId

Filter by certificate backend ID

signatureAlgorithm

Filter by certificate signature algorithm

keyAlgorithm

Filter by certificate public key algorithm

keyParam

Filter by certificate public key size or curve name

keyUsage

Filter by certificate key usage

extendedKeyUsage

Filter by certificate extended key usage

email

Filter by certificate person email

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2?size=10&position=0&personId=42&keyVault=true&certTypeId=100500&serialNumber=C3DB6F88E720DF99717059FBD02D29B0&backendCertId=12345&email=user%40ccmqa.com' -i -X GET \
+    -H 'login: admin_customer21226' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21226' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of client certificates available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of Client certificate properties

[].id

Number

Certificate ID

[].certificateDetails

Object

Certificate details

[].certificateDetails.issuer

String

The subject of the issuing CA certificate

[].certificateDetails.subject

String

The subject of CA certificate

[].certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

[].certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

[].certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

[].certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

[].state

String

Certificate state

[].orderNumber

Number

Certificate order number

[].serialNumber

String

Certificate serial number

[].backendCertId

String

Certificate ID in enrolling backend

[].expires

String

Certificate expiration date

[].comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 331
+
+[{"id":1,"state":"issued","certificateDetails":{"subject":"S/MIME Subject string","sha256Hash":"513b909ac0470c0fe23a2af2282b927d25fc590bda99c7dd505b093c975075c9"},"serialNumber":"C3:DB:6F:88:E7:20:DF:99:71:70:59:FB:D0:2D:29:B0","orderNumber":12345,"backendCertId":"12345","expires":"2345-06-07","comments":"S/MIME comment string"}]
+
+
+
+
+
+

Count client certificates

+
+

Count all client certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

keyVault

Filter by certificate Key Vault flag

personId

Filter by certificate person ID

state

Filter by certificate state. Possible values: ', 'blank', 'created', 'requested', 'issued', 'downloaded' - deprecated, 'expired', 'revoked', 'rejected', 'pre_revoked''

certTypeId

Filter by certificate profile ID

serialNumber

Filter by certificate serial number

backendCertId

Filter by certificate backend ID

signatureAlgorithm

Filter by certificate signature algorithm

keyAlgorithm

Filter by certificate public key algorithm

keyParam

Filter by certificate public key size or curve name

keyUsage

Filter by certificate key usage

extendedKeyUsage

Filter by certificate extended key usage

email

Filter by certificate person email

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2?personId=42&keyVault=true&certTypeId=100500&serialNumber=C3DB6F88E720DF99717059FBD02D29B0' -i -X HEAD \
+    -H 'login: admin_customer21223' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21223' \
+    -H 'Accept: application/json' \
+    -H 'Content-Type: application/x-www-form-urlencoded'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of client certificates available according to the filtering applied

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+
+
+
+
+
+

List client certificates by person ID

+
+

List all client certificates for a person with given ID.

+
+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/byPersonId/{pid}
ParameterDescription

pid

Person ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/byPersonId/1' -i -X GET \
+    -H 'login: admin_customer21220' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21220' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of Client certificate properties

[].id

Number

Certificate ID

[].certificateDetails

Object

Certificate details

[].certificateDetails.issuer

String

The subject of the issuing CA certificate

[].certificateDetails.subject

String

The subject of CA certificate

[].certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

[].certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

[].certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

[].certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

[].state

String

Certificate state

[].orderNumber

Number

Certificate order number

[].serialNumber

String

Certificate serial number

[].backendCertId

String

Certificate ID in enrolling backend

[].expires

String

Certificate expiration date

[].comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 325
+
+[{"id":1,"state":"issued","certificateDetails":{"subject":"S/MIME Subject string","sha256Hash":"513b909ac0470c0fe23a2af2282b927d25fc590bda99c7dd505b093c975075c9"},"serialNumber":"C3:DB:6F:88:E7:20:DF:99:71:70:59:FB:D0:2D:29:B0","orderNumber":12345,"backendCertId":"12345","expires":"2345-06-07","comments":"Test comments 1"}]
+
+
+
+
+
+

List client certificates by person email

+
+

List all client certificates for a person with given email.

+
+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/byPersonEmail/{email}
ParameterDescription

email

Person e-mail. Must be formatted as valid e-mail string. Also might need to be properly encoded as required by URL syntax standard. For example, the '@' character should be replaced with the %40 code, '.' - with %2E and so on.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/byPersonEmail/mailbox@domain.com' -i -X GET \
+    -H 'login: admin_customer21217' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21217' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of Client certificate properties

[].id

Number

Certificate ID

[].certificateDetails

Object

Certificate details

[].certificateDetails.issuer

String

The subject of the issuing CA certificate

[].certificateDetails.subject

String

The subject of CA certificate

[].certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

[].certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

[].certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

[].certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

[].state

String

Certificate state

[].orderNumber

Number

Certificate order number

[].serialNumber

String

Certificate serial number

[].backendCertId

String

Cert ID in enrolling backend

[].expires

String

Certificate expiration date

[].comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Disposition: inline;filename=f.txt
+Content-Type: application/json
+Content-Length: 325
+
+[{"id":1,"state":"issued","certificateDetails":{"subject":"S/MIME Subject string","sha256Hash":"513b909ac0470c0fe23a2af2282b927d25fc590bda99c7dd505b093c975075c9"},"serialNumber":"C3:DB:6F:88:E7:20:DF:99:71:70:59:FB:D0:2D:29:B0","orderNumber":12345,"backendCertId":"12345","expires":"2345-06-07","comments":"Test comments 1"}]
+
+
+
+
+
+

Client certificate details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/{id}
ParameterDescription

id

Client certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/139' -i -X GET \
+    -H 'login: admin_customer21353' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21353'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

subType

String

Certificate subtype

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

backendCertId

String

Certificate ID in enrolling backend

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

term

Number

Term (days)

requestedVia

String

Requested Via. Possible values: 'Admin Enroll', 'Self Enroll', 'API Enroll', 'Auto Enroll', 'CSV Enroll', 'SCEP Enroll', 'IdP Enroll', 'MS Agent Enroll', 'Discovery', 'MS CA Enroll', 'Imported', 'EST Enroll', 'REST Enroll API'

requested

String

Requested date

issued

String

Issued date

expires

String

Expiration date

revoked

String

Revocation date

reasonCode

Number

Revocation reason code provided on revoke to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

serialNumber

String

SSL Serial Number

signatureAlg

String

Signature Algorithm

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

keyUsages

Array

Key Usages

extendedKeyUsages

Array

Extended Key Usages

subjectAlternativeNames

Array

Subject alternative names

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

suspendNotifications

Boolean

Suspend Notifications for the certificate

comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 680
+
+{"commonName":"Tester","id":139,"orgId":3149,"status":"issued","backendCertId":"12345678","certType":{"id":2025,"name":"High Persona Validated Cert","terms":[365,730],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false},"subType":"Private","term":30,"requestedVia":"Self Enroll","comments":"client certificate 139","requested":"08/15/2025","issued":"08/15/2025","expires":"09/26/2025","keyAlgorithm":"RSA","keySize":2048,"keyType":"RSA - 2048","keyUsages":["Digital Signature","Key Encipherment"],"extendedKeyUsages":["1.3.6.1.5.5.7.3.4","1.3.6.1.5.5.7.3.2"],"certificateDetails":{"sha1Hash":"AAABBBCCC","sha256Hash":"AAABBBCCCddd"},"suspendNotifications":false}
+
+
+
+
+
+
+

Enroll client certificate

+
+

Request client certificate

+
+

Creation and submission of a request for a new Client certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

csr

String

Certificate signing request

certType

Number

Certificate Profile ID

term

Number

Certificate validity period in days

[Must be at least 1]

email

String

Person e-mail

[Must be a well-formed email address, Must not be empty, Maximum length is 128 characters or can be empty]

phone

String

Person telephone

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

secondaryEmails

Array

Person secondary e-mails

[]

firstName

String

Person first name

firstName must not be empty, firstName + ' ' + middleName + ' ' + lastName must be in range of 1 to 64 characters

middleName

String

Person middle name

firstName + ' ' + middleName + ' ' + lastName must be in range of 1 to 64 characters

lastName

String

Person last name

lastName must not be empty, firstName + ' ' + middleName + ' ' + lastName must be in range of 1 to 64 characters

customFields

Array

Custom fields to be applied to requested certificate

[]

commonName

String

Person’s common name, if omitted will be constructed from Person’s full name

[Maximum length is 64 characters or can be empty]

eppn

String

EPPN

[Maximum length is 128 characters or can be empty]

upn

String

Principal name

[Maximum length is 256 characters or can be empty]

comments

String

Certificate comments

[Maximum length is 1024 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/enroll' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21304' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21304' \
+    -d '{"orgId":3131,"firstName":"Name","middleName":"","lastName":"LastName","email":"name@test.net","phone":"12345678","secondaryEmails":[],"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC4jCCAcoCAQAwdDELMAkGA1UEBhMCVUExDTALBgNVBAgTBHRlc3QxDTALBgNV\nBAcTBHRlc3QxDTALBgNVBAoTBHRlc3QxDTALBgNVBAsTBHRlc3QxEjAQBgNVBAMT\nCWNjbXFhLmNvbTEVMBMGCSqGSIb3DQEJARYGdGVzdEB0MIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAul8SGkicOnrMjJDvgG8P2j1Ee5hY6ww+qSoe0oI2\ntvRcLBknPHMMAkxTjW9fy80wD8hyrnc+IGlQcq2R/tEMIJHRsJD603M+2FjAwlP9\n8xtiqv0hMyHO4fEt+HMyy8Q367aTBmnZCuAxJZJapfFW9wH5jGZxuX8mnrXVsBTD\n4ZBO4UFd9P4u8P0nJx80CiuDt4COSDl6Br4pNLciPVqfwj7LQ5/skwPkNCggk3/G\nxoQX/3FV7O4fC6WCxVP1uYjJVQjlD1Tf06hPNfonVfThVuP20OL3QAlnIF3lZiyY\nJ5etdFtu+BKcPNMdQDJOS/O4Zz0YJn6K2HdAXSc1YxYniwIDAQABoCkwJwYJKoZI\nhvcNAQkOMRowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQsF\nAAOCAQEAVJVTTELGHWoRh8JZt+kx/zO0VnibBq/D6uB405L+Ir80X48Ei9hTLB11\nAqhSBE+AbEgBhRnEIDBjiXEDcWvC532Omex721kc17ZTzowuD8lOjfQkTHbAmjIi\nnCQNFAPf0D/zpi6Eync5pi2P//Uj/Yn7oDYYli1t61EZwuQyEu4mbQ1efUnU/SOl\nAAQtDPhNwATZPmfefjM8+YuzhG70dQvmFAClcFayKM92Zx9khDd/VnLT85YzDULJ\n8iiHW8dZNblaTsUjKrc73iX2hONZIxw6B3tGCFs8mH9lZlExV7Y2er3t/lO1pdxe\nSUohEELWcttIxyWnYgxvwaWX4lfx9A==\n-----END CERTIFICATE REQUEST-----","certType":1992,"term":365,"customFields":[],"commonName":"Common name","upn":null,"eppn":null,"comments":"S/MIME comment string"}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderNumber

Number

Obsolete parameter for the order identifier under which the certificate request has been processed. BackendCertId should be used instead.

backendCertId

String

Certificate ID in enrolling backend

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 45
+
+{"orderNumber":12345,"backendCertId":"12345"}
+
+
+
+
+
+

Collect client certificate

+
+

Delivering the newly issued Client certificate from CA to the administrator for download.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/collect/{backendCertId}
ParameterDescription

backendCertId

Backend certificate ID

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

format

Format type for certificate. Allowed values: 'x509' - for Certificate (w/ chain), PEM encoded, 'x509CO' - for Certificate only, PEM encoded, 'base64' - for PKCS#7, PEM encoded, 'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded, 'x509IOR' - for Intermediate(s)/Root only, PEM encoded, 'pem' - for Certificate (w/ chain), PEM encoded, 'pemco' - for Certificate only, PEM encoded, 'pemia' - for Certificate (w/ issuer after), PEM encoded, 'x509R' - for Certificate (w/ chain), PEM encoded

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/collect/12345?format=base64' -i -X GET \
+    -H 'login: admin_customer21325' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21325'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/octet-stream
+Content-Disposition: attachment; filename="test_example_com.p7b"
+
+
+
+
+
+

Download P12 client certificate

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/keystore/{id}
ParameterDescription

id

Client certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

encryptionType

String

Encryption type for the keystore. Allowed values: AES256-SHA256, TripleDES-SHA1. Default AES256-SHA256

passphrase

String

Keystore passphrase

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/keystore/1' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21344' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21344' \
+    -d '{"passphrase":"12345678"}
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/octet-stream
+Content-Disposition: attachment; filename="key_vault.p12"
+Content-Length: 20
+
+[ BINARY BODY HERE ]
+
+
+
+
+
+
+

Manage client certificate

+
+

Update client certificate details

+
+

Update client certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

customFields

Array

Custom fields

[]

customFields[].name

String

Custom field name

[Must not be null, Size must be between 1 and 256 inclusive]

customFields[].value

String

Custom field value. For input type 'DATE' format is yyyy-MM-dd

[Must not be null, Maximum length is 256 characters or can be empty]

comments

String

Comments

[Maximum length is 1024 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/140' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer21403' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21403' \
+    -d '{
+  "customFields": [{"name": "test", "value": "value"}],
+  "comments": "client certificate"
+}
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

subType

String

Certificate subtype

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

backendCertId

String

Certificate ID in enrolling backend

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

term

Number

Term (days)

requestedVia

String

Requested Via. Possible values: 'Admin Enroll', 'Self Enroll', 'API Enroll', 'Auto Enroll', 'CSV Enroll', 'SCEP Enroll', 'IdP Enroll', 'MS Agent Enroll', 'Discovery', 'MS CA Enroll', 'Imported', 'EST Enroll', 'REST Enroll API'

requested

String

Requested date

issued

String

Issued date

expires

String

Expiration date

revoked

String

Revocation date

reasonCode

Number

Revocation reason code provided on revoke to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

serialNumber

String

SSL Serial Number

signatureAlg

String

Signature Algorithm

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

keyUsages

Array

Key Usages

extendedKeyUsages

Array

Extended Key Usages

subjectAlternativeNames

Array

Subject alternative names

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

suspendNotifications

Boolean

Suspend Notifications for the certificate

comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 508
+
+{"commonName":"Tester","id":140,"orgId":3166,"status":"created","backendCertId":"1","certType":{"id":2054,"name":"High Persona Validated Cert","terms":[365,730],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false},"subType":"Private","term":0,"requestedVia":"Self Enroll","comments":"client certificate","requested":"08/15/2025","keyAlgorithm":"RSA","keySize":2048,"keyType":"RSA - 2048","customFields":[{"name":"test","value":"value"}],"certificateDetails":{},"suspendNotifications":false}
+
+
+
+
+
+

Renew client certificate by backend certificate ID

+
+

Submission of a request for a new Client certificate using the CSR and parameters of the initial Client certificate. +The initial certificate is defined by its backend ID.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/renew/order/{backendCertId}
ParameterDescription

backendCertId

Backend certificate ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/renew/order/12345' -i -X POST \
+    -H 'login: admin_customer21268' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21268' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderNumber

Number

Obsolete parameter for the order identifier under which the certificate request has been processed. BackendCertId should be used instead.

backendCertId

String

Cert ID in enrolling backend

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 45
+
+{"orderNumber":12345,"backendCertId":"12345"}
+
+
+
+
+
+

Renew client certificate by serial number

+
+

Submission of a request for a new Client certificate using the CSR and parameters of the initial Client certificate. +The initial certificate is defined by its serial number.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v2/renew/serial/{serial}
ParameterDescription

serial

Serial number.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/renew/serial/test:serial' -i -X POST \
+    -H 'login: admin_customer21271' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21271' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderNumber

Number

Obsolete parameter for the order identifier under which the certificate request has been processed. BackendCertId should be used instead.

backendCertId

String

Cert ID in enrolling backend

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 45
+
+{"orderNumber":12345,"backendCertId":"12345"}
+
+
+
+
+
+

Replace client certificate by backend certificate ID

+
+

Deprecated. Please use enroll operation instead.

+
+
+
+

Revoke client certificate by backend certificate ID

+
+

Sending a request to CA to add the particular Client certificate in certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/revoke/order/{backendCertId}
ParameterDescription

backendCertId

Backend certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message explaining why certificate needs to be revoked

[Maximum length is 512 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/revoke/order/12345' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21384' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21384' \
+    -H 'Accept: application/json' \
+    -d '{"reasonCode":0,"reason":"my reason"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Revoke client certificate by serial number

+
+

Sending a request to CA to add the Client certificate under the particular serial number in certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/revoke/serial/{serialNumber}
ParameterDescription

serialNumber

Certificate serial number

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message explaining why certificate needs to be revoked

[Maximum length is 512 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/revoke/serial/test:serial' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21400' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21400' \
+    -H 'Accept: application/json' \
+    -d '{"reasonCode":1,"reason":"my reason"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+ +
+

Sending a request to CA to add all Client certificates issued for the person with the particular email address in certificate revocation list.

+
+
+ + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message explaining why certificate needs to be revoked

[Maximum length is 512 characters or can be empty]

email

String

Person e-mail address

+
+
+ +
+
+
$ curl 'https://cert-manager.com/api/smime/v1/revoke' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21381' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21381' \
+    -H 'Accept: application/json' \
+    -d '{"reasonCode":0,"reason":"my reason","email":"test@email"}'
+
+
+
+
+ +
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Manual Revoke client certificate by Id or serial number + issuer

+
+

Mark certificate as revoked. The certificate is not revoked on CA side.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

certId

Number

Certificate ID. Required if serialNumber and issuer are not provided.

Must be present if serialNumber and issuer are not provided

serialNumber

Number

Certificate serial number. Required if certId is not provided (used together with issuer).

Must be present with issuer if certId is not provided

issuer

Number

Certificate issuer. Required if certId is not provided (used together with serialNumber).

Must be present with serialNumber if certId is not provided

revokeDate

String

Certificate revoke date

[]

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/revoke/manual' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21363' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21363' \
+    -d '{"certId":1,"serialNumber":null,"issuer":null,"revokeDate":"2025-06-10T00:00:00Z","reasonCode":4}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete client certificate by Id

+
+

Submission of a request for deleting Client certificate for a given Id.

+
+
+ + + + + +
+ + +Only imported or discovered certificates can be deleted. +
+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/smime/v1/{certId}
ParameterDescription

certId

Certificate ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v1/138' -i -X DELETE \
+    -H 'login: admin_customer21337' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21337'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Import client certificates to SCM

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

[]

Array

Certificates to import

Should not be empty, maximum size is 128

[].orgID

Number

Organization ID

[Must be at least 1, Must not be null]

[].customFields

Array

List of custom certificate fields

[]

[].customFields[].name

String

Custom field name

[]

[].customFields[].value

String

Custom field value

[]

[].backendCertId

String

Backend certificate identifier

[Maximum length is 255 characters or can be empty]

[].cert

String

DER (Base64) certificate

[Must not be empty]

[].csr

String

DER (Base64) Certificate Signing Request

[]

[].comments

String

Additional comments

[Maximum length is 1024 characters or can be empty]

[].force

Boolean

Force alter editable certificate fields event if certificate is already exists.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/smime/v2/import' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21247' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21247' \
+    -d '[{"orgID":3106,"customFields":[{"name":"testName","value":"testValue"}],"backendCertId":"1234567890DFa","cert":"MIIECjCCA5CgAwIBAgIQfTldecXEba+DnvFWPQMZYzAKBggqhkjOPQQDAjBmMQswCQYDVQQGEwJVQTEWMBQGA1UECBMNT2Rlc2thIG9ibGFzdDEPMA0GA1UEBxMGT2Rlc3NhMRIwEAYDVQQKEwlBZHYuQ3VzdDIxGjAYBgNVBAMTEUFkdi5DdXN0MiBSb290IENBMB4XDTI0MDUxNTE3Mjg0OFoXDTI1MDUxNTE3Mjg0OFowTDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FsYWJhbWExETAPBgNVBAoTCEFkdmFuY2VkMRgwFgYDVQQDEw9SdXNsYW4gU2hpcG9zaGEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClKHtE9Bbtge/cWYAWr+/JJ0X7Vm3ReQmTunfEG4n9xTN4gvqypPHu05mCw/Ez3tr5939RnvfX/FJGAz/vHat2GtmSZaTOLJl8U9kTb/bCSJx9E8W90Lg6Go1WBItiZm0EmWQECtZfwx4vd12KqZCo3uQD83DqS4mwg5h25NmelLm8Rctfq/+Mk+/iAQIeaN8u5X97lxjXz6qAUa8sQTPP0zhHUfiN0v6yX3GHssbYAhoRFwUkKRDRgJPglRT9sq082u68FOAT5O5ri2+2v8CTO3aQk6CSXNOmSgKS/gTOBixfIpUYlCNx3bryhUyA1ZMAy4Kc+YOTCHJfsWRwbO51AgMBAAGjggFtMIIBaTAfBgNVHSMEGDAWgBSJ87Jc1mpY1qM60+FxgUHI721OsDAOBgNVHQ8BAf8EBAMCBaAwCQYDVR0TBAIwADAdBgNVHSUEFjAUBggrBgEFBQcDBAYIKwYBBQUHAwIwRwYDVR0fBEAwPjA8oDqgOIY2aHR0cDovL2NybC5kZXYuc2VjdGlnby5uZXQ6ODA4MC9BZHZhbmNlZFByaXZhdGVDQTIuY3JsMIGABggrBgEFBQcBAQR0MHIwQgYIKwYBBQUHMAKGNmh0dHA6Ly9jcnQuZGV2LnNlY3RpZ28ubmV0OjgwODAvQWR2YW5jZWRQcml2YXRlQ0EyLmNydDAsBggrBgEFBQcwAYYgaHR0cDovL29jc3AuZGV2LnNlY3RpZ28ubmV0OjgwODAwIQYDVR0RBBowGIEWc29tZW9uZWxpa2V1QGNjbXFhLmNvbTAdBgNVHQ4EFgQUGtwJd4SdJ8ndenHBTYZym1iRxZ4wCgYIKoZIzj0EAwIDaAAwZQIwYnQ1SwG/xS1R+pOq5TgNvId/HBF9BaEREyY7y31RACjHyf4yN/1D5m5Y2NWxQRxmAjEAv8LHLQYknt0v+is3C9qvPTkRos3zPZllKyEnv9VKRuYLr2RUY4liHVZN7jM81e4D","csr":"MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCY24xDzANBgNVBAgTBmJlaWppbjEQMA4GA1UEBxMHYmVpamluZzEPMA0GA1UEChMGQ09NT0RPMRAwDgYDVQQLEwdkZXZlbG9wMREwDwYDVQQDDAgqLmNtLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxrVE6cqSTe+jOsyYjBNw+5uZeDdu37bRgw6qQo2uSFhOhXyhsxcb0zaitpjNYLsEc4fp0YzNYrqzmIHK7HpgHgg9N9CVr0m2O/RlV761s257expajU1vYzVDIt/levLkOJe96++tOFOQ+6hrFnI2YWKxLdE+X0F7tGrDgkV2xXhW7qbw32C2kRyui3KvgoJ0Mwtwe0Gp6VVN61oNoinf5F/O8MGMFmM4TaRgSTcvWIJvrfuMTmHi9S918LfQRrFGfDKNX49iS8oWT7SVBmLxjcEqIsTfCFo9rg/aP8elS3kRFBH8fTNUPjcOCa/Km6JoIM4C/KEro6uraXAbl+QhMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQBvyheU7vn+VCQJz8OHVD2r9c79KETEeaTMIvnTjGECd3RlXXErcFxuvFJYtTyiNZwzyRi7Q4IBp8g41UYRsBsMim0ioQdW9cIIMMn0oY7oAuQt6eM77iOd/bWhpGAPKe6rG8vadA6nF+hPIPEkqIlfWYNc/ZarvXr2UPNmYdv/skDi9PQUlzB1xOWQUO3Li+QYZWuE3UjLDNCoh5uTY5UMn/K+Ej8fDDz4mc4zZQQf3mASZcMEv75pqfEiRY1zUUPLLT5vUZ5yh32DG8mm+X5Gkr1xQNYGAUymxTdG2ct2t3xxLjGmRABxPvGNIrIefboyLma9Yd0GBOtrexsNzbUI","comments":"Test comments","force":true}]'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of certificates

[].cert

Object

Client certificate information

[].cert.id

Number

Client certificate ID

[].cert.subject

String

Client certificate Subject

[].cert.serialNumber

String

Client certificate Serial Number

[].created

Boolean

Whether certificate been created or not (it could already exist)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 144
+
+[{"cert":{"id":127,"subject":"CN=Ruslan Shiposha,O=Advanced,ST=Alabama,C=US","serialNumber":"7D395D79C5C46DAF839EF1563D031963"},"created":true}]
+
+
+
+
+

The response array element can be error message:

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[].errorMessage

String

Error message

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 171
+
+[{"errorMessage":"Certificate under serial number ''E11BBD70D54B710D0C6F540B6B52CA4'' cannot be managed as a certificate of ''Client cert'' type. CN must contain email."}]
+
+
+
+
+
+
+
+
+

Device Certificates

+
+
+

Used to perform operations on device certificates.

+
+
+

Device certificate helper APIs

+
+

List device certificate Profiles

+
+

List device certificate profiles, previously known as a certificate type. An enrollment request will require the certificate profile be specified.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

organizationId

Filter by Organization ID (optional)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/types?organizationId=928' -i -X GET \
+    -H 'login: admin_customer1583' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1583' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of available certificate profiles

[].id

Number

Certificate Profile ID

[].name

String

Certificate Profile name

[].description

String

Certificate Profile description

[].term

Number

First available term (in days) for the Certificate Profile

[].useSecondaryOrgName

Boolean

Use secondary organization name

[].terms

Array

Terms (in days) available for the Certificate Profile

[].keyTypes

Object

Key types available for the Certificate Profile

[].ku[]

Array

Key Usages available for the Certificate Profile

[].eku[]

Array

Extended Key Usages available for the Certificate Profile

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 261
+
+[{"id":1256,"name":"Device cert SASP 151833396","description":"Device cert SASP 1837829685","terms":[365],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false,"term":365,"ku":["Digital Signature","Non repudiation"],"eku":["1.3.6.1.5.5.7.3.2"]}]
+
+
+
+
+
+

List device certificate custom fields

+
+

List device certificate custom fields. An enrollment require will require all mandatory custom fields be specified.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/customFields' -i -X GET \
+    -H 'login: admin_customer1587' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1587' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of custom fields

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatory

Boolean

Is field mandatory

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 46
+
+[{"id":60,"name":"testName","mandatory":true}]
+
+
+
+
+
+
+

Device certificate locations

+
+

List device certificate locations

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}/location
ParameterDescription

certId

Certificate ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/78/location' -i -X GET \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer1597' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1597'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Device Certificate Locations

[].id

Number

Location ID

[].locationType

String

Location Type

[].name

String

Location Name (optional)

[].details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 150
+
+[{"id":62,"locationType":"CUSTOM","name":"","details":{"location1":"PC"}},{"id":63,"locationType":"CUSTOM","name":"","details":{"location2":"Phone"}}]
+
+
+
+
+
+

Create custom location for device certificate

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}/location
ParameterDescription

certId

Certificate ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/65/location' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer1557' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1557' \
+    -d '{"details":{"device":"Tablet"}}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of the created certificate location entity

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/device/v1/65/location/59
+
+
+
+
+
+

Get details of device certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/76/location/61' -i -X GET \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer1591' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1591'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Location ID

locationType

String

Location Type

name

String

Location Name (optional)

details

Object

Location Details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 72
+
+{"id":61,"locationType":"CUSTOM","name":"","details":{"Device":"Phone"}}
+
+
+
+
+
+

Update device certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

details

Object

Location details in key-value format that should be applied.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/119/location/64' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer1722' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1722' \
+    -d '{"details":{"device":"Laptop"}}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete device certificate’s custom location

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}/location/{locationId}
ParameterDescription

certId

Certificate ID

locationId

Location ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/70/location/60' -i -X DELETE \
+    -H 'login: admin_customer1569' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1569'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

View device certificates

+
+

List device certificates

+
+

List all device certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

commonName

Filter by certificate common name

email

Filter by certificate requester email

status

Filter by certificate status. Possible values: , 'REQUESTED', 'APPROVED', 'DECLINED', 'APPLIED', 'ISSUED', 'DOWNLOADED' - deprecated, 'EXPIRED', 'REVOKED', 'REJECTED', 'AWAITING_APPROVAL' - deprecated (falls back to 'REQUESTED', please use new status instead)

orgId

Filter by certificate organization ID

certTypeId

Filter by certificate profile ID

serialNumber

Filter by certificate serial number

backendCertId

Deprecated Filter by ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

signatureAlgorithm

Filter by certificate signature algorithm

keyAlgorithm

Filter by certificate public key algorithm

keyParam

Filter by certificate public key size or curve name

keyUsage

Filter by certificate key usage

extendedKeyUsage

Filter by certificate extended key Usage

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1?size=10&position=0&commonName=34356576543tnl54hgnu49u90g&email=Someone%40nobody.sectigo.com&status=APPROVED&certTypeId=1264' -i -X GET \
+    -H 'login: admin_customer1619' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1619'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of device certificates available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested device certificates

[].id

Number

Unique ID for certificate. Known as deviceCertId in some methods. This ID should be used for certificate operations.

[].backendCertId

String

ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

[].status

String

Certificate status

[].certificateDetails

Object

Certificate details

[].certificateDetails.issuer

String

The subject of the issuing CA certificate

[].certificateDetails.subject

String

The subject of CA certificate

[].certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

[].certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

[].certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

[].certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 153
+
+[{"id":87,"status":"APPROVED","backendCertId":"1622","certificateDetails":{"subject":"C=UA,ST=Odessa,L=Odessa,O=Test,OU=Test,CN=Test,E=test@test.test"}}]
+
+
+
+
+
+

Count device certificates

+
+

Count all device certificates that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

commonName

Filter by certificate common name

email

Filter by certificate requester email

status

Filter by certificate status. Possible values: ', 'REQUESTED', 'APPROVED', 'DECLINED', 'APPLIED', 'ISSUED', 'DOWNLOADED' - deprecated, 'EXPIRED', 'REVOKED', 'REJECTED', 'AWAITING_APPROVAL' - deprecated (falls back to 'REQUESTED', please use new status instead)'

orgId

Filter by certificate organization ID

certTypeId

Filter by certificate profile ID

serialNumber

Filter by certificate serial number

backendCertId

Deprecated Filter by ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

signatureAlgorithm

Filter by certificate signature algorithm

keyAlgorithm

Filter by certificate public key algorithm

keyParam

Filter by certificate public key size or curve name

keyUsage

Filter by certificate key usage

extendedKeyUsage

Filter by certificate extended key Usage

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1?commonName=34356576543tnl54hgnu49u90g&orgId=912&status=APPROVED' -i -X HEAD \
+    -H 'login: admin_customer1553' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1553' \
+    -H 'Content-Type: application/x-www-form-urlencoded'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of device certificates available according to the filtering applied

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+
+
+
+
+
+

Get device certificate details

+
+

Get device certificate details.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/58' -i -X GET \
+    -H 'login: admin_customer1533' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1533'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

id

Number

Unique ID for certificate. Known as deviceCertId in some methods. This ID should be used for certificate operations.

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

orderNumber

Number

Deprecated. Old numeric form of backendCertId. backendCertId is new field but should not be used for certificate operations.

backendCertId

String

ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

term

Number

Term (days)

owner

String

The approver of the request for this certificate

requester

String

Requester

requested

String

Requested date

approved

String

Approved date

expires

String

Expiration date

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

serialNumber

String

SSL Serial Number

comments

String

Certificate comments

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 599
+
+{"commonName":"34356576543tnl54hgnu49u90g","id":58,"orgId":902,"status":"Approved","orderNumber":1536,"backendCertId":"1536","certType":{"id":1243,"name":"Test device type","description":"Device cert profile","terms":[365],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false},"term":365,"requester":"Someone@nobody.sectigo.com","comments":"Device certificate comment string","requested":"08/15/2025","expires":"08/15/2026","keyAlgorithm":"RSA","keySize":2048,"keyType":"RSA - 2048","certificateDetails":{"subject":"C=UA,ST=Odessa,L=Odessa,O=Test,OU=Test,CN=Test,E=test@test.test"}}
+
+
+
+
+
+
+

Enroll device certificate

+
+

Request device certificate

+
+

Creation and submission of a request for a new Device certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

'Must be at least 1,Must not be null'

csr

String

Certificate signing request

'Must match the regular expression [a-zA-Z0-9-=\/\s],Must not be empty,Size must be between 1 and 32767 inclusive'

certType

Number

Certificate Profile ID

'Must be at least 1,Must not be null'

term

Number

Certificate validity period in days

'Must be at least 1'

comments

String

Certificate comments

[Maximum length is 1024 characters or can be empty]

customFields[]

Array

Custom fields to be applied to requested certificate. Must contain mandatory custom fields.

customFields[].name

String

Name of an enabled custom field.

[]

customFields[].value

String

Value of the custom field. For input type 'DATE' format is yyyy-MM-dd

[]

optionalFields[]

Array

Optional fields to be applied to requested certificate

[]

optionalFields[].name

String

Name of supported optional field.

Must be one of the following values: [commonName, surname, countryName, localityName, stateOrProvinceName, streetAddress, organizationName, organizationalUnitName, title, description, postalCode, postOfficeBox, telephoneNumber, givenName, initials, emailAddress, DocumentoNacionaldeIdentidad, serialNumber, SIRENE, collectionEmailAddress, rfc822Name, subjectUniqueIdentifier, uniqueIdentifier, PermIdAscentMediaNetSecDept, PermIdAscentMediaEngHomeNet, sAMAccountName, userId, userPrincipalName, unstructuredName, domainComponent, dnsName, servicePrincipalName, eeSID]

optionalFields[].value

String

Value of the optional field.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/enroll' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1575' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1575' \
+    -d '{"orgId":924,"term":365,"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC4jCCAcoCAQAwdDELMAkGA1UEBhMCVUExDTALBgNVBAgTBHRlc3QxDTALBgNV\nBAcTBHRlc3QxDTALBgNVBAoTBHRlc3QxDTALBgNVBAsTBHRlc3QxEjAQBgNVBAMT\nCWNjbXFhLmNvbTEVMBMGCSqGSIb3DQEJARYGdGVzdEB0MIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAul8SGkicOnrMjJDvgG8P2j1Ee5hY6ww+qSoe0oI2\ntvRcLBknPHMMAkxTjW9fy80wD8hyrnc+IGlQcq2R/tEMIJHRsJD603M+2FjAwlP9\n8xtiqv0hMyHO4fEt+HMyy8Q367aTBmnZCuAxJZJapfFW9wH5jGZxuX8mnrXVsBTD\n4ZBO4UFd9P4u8P0nJx80CiuDt4COSDl6Br4pNLciPVqfwj7LQ5/skwPkNCggk3/G\nxoQX/3FV7O4fC6WCxVP1uYjJVQjlD1Tf06hPNfonVfThVuP20OL3QAlnIF3lZiyY\nJ5etdFtu+BKcPNMdQDJOS/O4Zz0YJn6K2HdAXSc1YxYniwIDAQABoCkwJwYJKoZI\nhvcNAQkOMRowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQsF\nAAOCAQEAVJVTTELGHWoRh8JZt+kx/zO0VnibBq/D6uB405L+Ir80X48Ei9hTLB11\nAqhSBE+AbEgBhRnEIDBjiXEDcWvC532Omex721kc17ZTzowuD8lOjfQkTHbAmjIi\nnCQNFAPf0D/zpi6Eync5pi2P//Uj/Yn7oDYYli1t61EZwuQyEu4mbQ1efUnU/SOl\nAAQtDPhNwATZPmfefjM8+YuzhG70dQvmFAClcFayKM92Zx9khDd/VnLT85YzDULJ\n8iiHW8dZNblaTsUjKrc73iX2hONZIxw6B3tGCFs8mH9lZlExV7Y2er3t/lO1pdxe\nSUohEELWcttIxyWnYgxvwaWX4lfx9A==\n-----END CERTIFICATE REQUEST-----","certType":1253,"customFields":[{"name":"custom field","value":"custom field value"}],"optionalFields":[{"name":"commonName","value":"test.example.com"}],"comments":"Device certificate comment string"}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

deviceCertId

Number

Unique ID for certificate. This ID should be used for certificate operations.

status

String

Certificate status.

backendCertId

String

Deprecated. ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

orderNumber

Number

Deprecated. Currently identical to deviceCertId for backwards compatibility during migration phase.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 79
+
+{"deviceCertId":71,"status":"APPROVED","backendCertId":"1578","orderNumber":71}
+
+
+
+
+
+

Collect device certificate

+
+

Delivering the newly issued Device certificate from CA to the administrator for download.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/collect/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

format

Format type name for certificate. If not specified, PKCS#7 Base64 encoded is default. Allowed values: 'x509R' - for Certificate (w/ chain), PEM encoded, 'x509' - for Certificate (w/ chain), PEM encoded, 'pem' - for Certificate (w/ chain), PEM encoded, 'x509CO' - for Certificate only, PEM encoded, 'pemco' - for Certificate only, PEM encoded, 'x509IO' - for Root/Intermediate(s) only, PEM encoded, 'x509IOR' - for Intermediate(s)/Root only, PEM encoded, 'pemia' - for Certificate (w/ issuer after), PEM encoded, 'base64' - for PKCS#7, PEM encoded, 'bin' - for PKCS#7

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/collect/132132?format=base64' -i -X GET \
+    -H 'login: admin_customer1537' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1537'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Length: 3218
+Content-Type: application/octet-stream
+Content-Disposition: attachment; filename="test.cert"
+
+-----BEGIN PKCS7-----
+MIIJJQYJKoZIhvcNAQcCoIIJFjCCCRICAQExADALBgkqhkiG9w0BBwGgggj6MIIF
+HjCCBAagAwIBAgIQBXQwB2XNLnzRqXF67yXetTANBgkqhkiG9w0BAQsFADCBgzEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKTAnBgNVBAMT
+IFRlc3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE3MTEyNzAwMDAw
+MFoXDTE4MTEyNzIzNTk1OVowaTELMAkGA1UECxMCSVQxFzAVBgNVBAoTDk15Q29t
+cGFueSBMdGQuMQ4wDAYDVQQIEwVZb3JrczENMAsGA1UEBxMEWW9yazELMAkGA1UE
+BhMCR0IxFTATBgNVBAMTDHR0LmNjbXFhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMjaijCapexR3eiRTcRrJNF3jqF9msby8qRvDHK5MNJ3WMQU
+HgtcxSVRItBBV9M0GM2agG/+zOCvez71n2IfMoqqouZRfBsw7DMqnVMGQVYhBfVE
+Mr2fsP0BGk1SdGaoZYgACKUkjc7MbdESyJhmEvEYIBpdVHzqDU2dJ2Op1t2G7Kpb
+rzpRupMqmuQybGqJlidnicFf9irDcqd22Koih9TjfKM/4ZYMCBs3fv0bZVyM9Alh
+lOEMFj1ytmcGLHa5ojnX1lLT4xjZNFaJJv9ZwNYAA+YkE29q7uJZINPcTf+CfqUe
+UEWdq5cBiAPoPMrtsHimfLEvf3UmRxKhzNYEv6kCAwEAAaOCAaUwggGhMB8GA1Ud
+IwQYMBaAFIaGHcsGJX0nAVdr5Wo40OREr5MyMB0GA1UdDgQWBBTXOsPzzx5rZ2/g
+MmTvN+0y0Ys3XTAOBgNVHQ8BAf8EBAMCA/gwDAYDVR0TAQH/BAIwADAdBgNVHSUE
+FjAUBggrBgEFBQcDBAYIKwYBBQUHAwIwEQYJYIZIAYb4QgEBBAQDAgWgMEYGA1Ud
+IAQ/MD0wOwYMKwYBBAGyMQECAQMFMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2Vj
+dXJlLmNvbW9kby5uZXQvQ1BTMEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly9jcmwu
+Y29tb2RvY2EuY29tL1Rlc3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB7
+BggrBgEFBQcBAQRvMG0wRQYIKwYBBQUHMAKGOWh0dHA6Ly9jcnQuY29tb2RvY2Eu
+Y29tL1Rlc3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNydDAkBggrBgEFBQcw
+AYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAA
+AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8w
+MTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9g
+YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+Q
+kZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/A
+wcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq6+zt7u/w
+8fLz9PX29/j5+vv8/f7/MIID1DCCArygAwIBAgIQHpFpjHVf56b6C+OC9siGTDAN
+BgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg
+TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENB
+IExpbWl0ZWQxKTAnBgNVBAMTIFRlc3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MB4XDTE0MDEwMTAwMDAwMFoXDTMwMTIzMTIzNTk1OVowgYMxCzAJBgNVBAYT
+AkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZv
+cmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSkwJwYDVQQDEyBUZXN0IFJT
+QSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL/ZSIMZBY4Ifq5oXcdSPDa5ArrYahP4qhO9aES9jT7TEr5tpNIQ
+QP044h+3MGc7Cgf17OYSqpd4WvvhgUCkc8XDda3JgKEgCaHfnjgynBtXk6JP8stM
+IuKPZS9WcEQSKB7JPOnjaHdBkLRfbuSu0y7he9IoibiSCIU5mJ8T6QNd5wEWBp4j
+gRQWnLBXtJENtCzcU5j2sPh0gZUFjlu1V3Cc8JUENzDpMpjtxNYHtbL68BFXcWvy
+7hrqnE4eNM5K3DfEacdrvFgIQNfCMc4KEh2DFzDoCZpchDLhVGrYrTObG4D/RR0o
+T2QuFqbaiatLcG/armNUgb+4VH1R/HOQaf0CAwEAAaNCMEAwHQYDVR0OBBYEFIaG
+HcsGJX0nAVdr5Wo40OREr5MyMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCeQAWeNNtsKuUt5V9JifMy2AduOcK7lndh
+M24L8KG86o7aoye1QDqMfFmUrFo7nDVno6G013PnRo97BcrVPoMVB66TP5LywOrL
+rVoiIF9I5OD4BrtgvrRtlT3iMZwxjzU19lgEcLs+sJZhug2eDKAjp0PaJ40Wg5sn
+o3CRq/urYgtIAiFdxgMBefK0Ejivos5RLDzmHjA/Wo+jFMfXvdP6RxVmz7Nxfcws
+I+sOSWmb60dZlaC1yVZ0PbD2DFj7yEnW94p86d7Thmv6ksaqbOeWdJErnYJkqXPB
+0wSazHQeQHjWp91j4ZwlYRhZQfovwiRi601iWNNE7hPrMb87FkvyMQA=
+-----END PKCS7-----
+
+
+
+
+
+
+

Manage device certificate

+
+

Update device certificate details

+
+

Update device certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

customFields

Array

Custom fields

[]

customFields[].name

String

Custom field name

[Must not be null, Size must be between 1 and 256 inclusive]

customFields[].value

String

Custom field value. For input type 'DATE' format is yyyy-MM-dd

[Must not be null, Maximum length is 256 characters or can be empty]

comments

String

Comments

[Maximum length is 1024 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/117' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer1717' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1717' \
+    -d '{
+  "customFields": [{"name": "test", "value": "value"}],
+  "comments": "device certificate"
+}
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

commonName

String

Certificate common name

id

Number

Unique ID for certificate. Known as deviceCertId in some methods. This ID should be used for certificate operations.

orgId

Number

An organization which this certificate is associated with

status

String

The status of this certificate

orderNumber

Number

Deprecated. Old numeric form of backendCertId. backendCertId is new field but should not be used for certificate operations.

backendCertId

String

ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

certType

Object

Information about Certificate Profile this certificate was enrolled from

certType.id

Number

Certificate Profile ID

certType.useSecondaryOrgName

Boolean

Use secondary organization name

certType.name

String

Certificate Profile name

certType.description

String

Certificate Profile description

certType.terms

Array

Terms (in days) available for the Certificate Profile

certType.keyTypes

Object

Key types available for the Certificate Profile

term

Number

Term (days)

owner

String

The approver of the request for this certificate

requester

String

Requester

requested

String

Requested date

approved

String

Approved date

expires

String

Expiration date

keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

keySize

Number

Key size (deprecated, see "keyType")

keyType

String

Key type. For example: RSA - 2048, EC - P-256.

serialNumber

String

SSL Serial Number

comments

String

Certificate comments

customFields.[]

Array

Custom fields

customFields.[].name

String

Custom field name

customFields.[].value

String

Custom field value

certificateDetails

Object

Certificate details

certificateDetails.issuer

String

The subject of the issuing CA certificate

certificateDetails.subject

String

The subject of CA certificate

certificateDetails.subjectAltNames

String

The subject alternative names of the issuing CA certificate

certificateDetails.md5Hash

String

The MD5 fingerprint of CA certificate

certificateDetails.sha1Hash

String

The SHA1 fingerprint of CA certificate

certificateDetails.sha256Hash

String

The SHA256 fingerprint of CA certificate

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 553
+
+{"commonName":"device cert","id":117,"orgId":1004,"status":"Issued","orderNumber":111111,"backendCertId":"111111","certType":{"id":1288,"name":"Device cert SASP 1776429334","description":"Device cert SASP -1835101769","terms":[180],"keyTypes":{"RSA":["1024","2048","4096"]},"useSecondaryOrgName":false},"term":0,"requester":"test@4v2la.com","comments":"device certificate","requested":"08/15/2025","expires":"02/11/2026","keyAlgorithm":"RSA","keySize":2048,"keyType":"RSA - 2048","customFields":[{"name":"test","value":"value"}],"certificateDetails":{}}
+
+
+
+
+
+

Approve device certificate

+
+

Allows admin to approve the requested Device certificate.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/approve/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

message

String

Short message containing accompanying information for certificate approval action

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/approve/57' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1529' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1529' \
+    -d '{"message":"Approval message"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Decline device certificate

+
+

Allows admin to decline the requested Device certificate.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/decline/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

message

String

Short message containing accompanying information for certificate declining action

[Must not be empty, Size must be between 1 and 512 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/decline/66' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1561' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1561' \
+    -d '{"message":"Decline message"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Revoke device certificate by Id

+
+

Sending a request to CA to add the Device certificate under the particular Id to certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/revoke/order/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message explaining why certificate needs to be revoked

[Maximum length is 512 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/revoke/order/125546' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1689' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1689' \
+    -d '{"reasonCode":4,"reason":"my reason"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Revoke device certificate by serial number

+
+

Sending a request to CA to add the Device certificate under the particular serial number to certificate revocation list.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/revoke/serial/{serialNumber}
ParameterDescription

serialNumber

Certificate Serial Number

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

reason

String

Short message explaining why certificate needs to be revoked

[Maximum length is 512 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/revoke/serial/A7:35:E0:9A:D6:D1:C0:CC:56:EA:6C:D0:E3:97:B6:D9' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1701' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1701' \
+    -d '{"reasonCode":4,"reason":"my reason"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Manual Revoke device certificate by Id or serial number + issuer

+
+

Mark certificate as revoked. The certificate is not revoked on CA side.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

certId

Number

Certificate ID. Required if serialNumber and issuer are not provided.

Must be present if serialNumber and issuer are not provided

serialNumber

Number

Certificate serial number. Required if certId is not provided (used together with issuer).

Must be present with issuer if certId is not provided

issuer

Number

Certificate issuer. Required if certId is not provided (used together with serialNumber).

Must be present with serialNumber if certId is not provided

revokeDate

String

Certificate revoke date

[]

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/revoke/manual' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1627' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1627' \
+    -d '{"certId":91,"serialNumber":null,"issuer":null,"revokeDate":"2025-06-10T00:00:00Z","reasonCode":4}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Renew device certificate by Id

+
+

Submission of a request for a new Device certificate using the CSR and parameters of the initial Device certificate. +The initial certificate is defined by its Id.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/renew/order/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/renew/order/12345' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1651' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1651'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

deviceCertId

Number

Unique ID for certificate. This ID should be used for certificate operations.

status

String

Certificate status.

backendCertId

String

Deprecated. ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

orderNumber

Number

Deprecated. Currently identical to deviceCertId for backwards compatibility during migration phase.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 79
+
+{"deviceCertId":99,"status":"APPROVED","backendCertId":"1654","orderNumber":99}
+
+
+
+
+
+

Renew device certificate by serial number

+
+

Submission of a request for a new Device certificate using the CSR and parameters of the initial Device certificate. +The initial certificate is defined by its serial number.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/renew/serial/{serialNumber}
ParameterDescription

serialNumber

Serial Number of certificate which you are going to renew.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/renew/serial/A7:35:E0:9A:D6:D1:C0:CC:56:EA:6C:D0:E3:97:B6:D9' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1673' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1673'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

deviceCertId

Number

Unique ID for certificate. This ID should be used for certificate operations.

status

String

Certificate status.

backendCertId

String

Deprecated. ID of certificate in the enrolling backend. Should not be used for certificate operations but will work during migration phase.

orderNumber

Number

Deprecated. Currently identical to deviceCertId for backwards compatibility during migration phase.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 81
+
+{"deviceCertId":104,"status":"APPROVED","backendCertId":"1676","orderNumber":104}
+
+
+
+
+
+

Replace device certificate by Id

+
+

Submission of a request for a replace of a Device certificate using new CSR and the parameters of the initial Device certificate. +The initial certificate is defined by its Id.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/replace/order/{deviceCertId}
ParameterDescription

deviceCertId

Unique ID for certificate.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

csr

String

Certificate signing request related to new key pair

[Must match the regular expression [a-zA-Z0-9-=\/\s], Must not be empty, Size must be between 1 and 32767 inclusive]

reason

String

Short message explaining why certificate needs to be replaced

[Must not be empty, Size must be between 1 and 512 inclusive]

revoke

Boolean

Previous certificate will be revoked if true

[Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/replace/order/252' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1681' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1681' \
+    -d '{"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC4jCCAcoCAQAwdDELMAkGA1UEBhMCVUExDTALBgNVBAgTBHRlc3QxDTALBgNV\nBAcTBHRlc3QxDTALBgNVBAoTBHRlc3QxDTALBgNVBAsTBHRlc3QxEjAQBgNVBAMT\nCWNjbXFhLmNvbTEVMBMGCSqGSIb3DQEJARYGdGVzdEB0MIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAul8SGkicOnrMjJDvgG8P2j1Ee5hY6ww+qSoe0oI2\ntvRcLBknPHMMAkxTjW9fy80wD8hyrnc+IGlQcq2R/tEMIJHRsJD603M+2FjAwlP9\n8xtiqv0hMyHO4fEt+HMyy8Q367aTBmnZCuAxJZJapfFW9wH5jGZxuX8mnrXVsBTD\n4ZBO4UFd9P4u8P0nJx80CiuDt4COSDl6Br4pNLciPVqfwj7LQ5/skwPkNCggk3/G\nxoQX/3FV7O4fC6WCxVP1uYjJVQjlD1Tf06hPNfonVfThVuP20OL3QAlnIF3lZiyY\nJ5etdFtu+BKcPNMdQDJOS/O4Zz0YJn6K2HdAXSc1YxYniwIDAQABoCkwJwYJKoZI\nhvcNAQkOMRowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQsF\nAAOCAQEAVJVTTELGHWoRh8JZt+kx/zO0VnibBq/D6uB405L+Ir80X48Ei9hTLB11\nAqhSBE+AbEgBhRnEIDBjiXEDcWvC532Omex721kc17ZTzowuD8lOjfQkTHbAmjIi\nnCQNFAPf0D/zpi6Eync5pi2P//Uj/Yn7oDYYli1t61EZwuQyEu4mbQ1efUnU/SOl\nAAQtDPhNwATZPmfefjM8+YuzhG70dQvmFAClcFayKM92Zx9khDd/VnLT85YzDULJ\n8iiHW8dZNblaTsUjKrc73iX2hONZIxw6B3tGCFs8mH9lZlExV7Y2er3t/lO1pdxe\nSUohEELWcttIxyWnYgxvwaWX4lfx9A==\n-----END CERTIFICATE REQUEST-----","reason":"Test","revoke":false}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete device certificate by Id

+
+

Submission of a request for deleting Device certificate for a given Id.

+
+
+ + + + + +
+ + +Only imported or discovered certificates can be deleted. +
+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/device/v1/{certId}
ParameterDescription

certId

Certificate ID.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/68' -i -X DELETE \
+    -H 'login: admin_customer1565' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1565'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Import device certificates to SCM

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

[]

Array

Certificates to import

Should not be empty, maximum size is 128

[].orgID

Number

Organization ID

[Must be at least 1, Must not be null]

[].customFields

Array

List of custom certificate fields

[]

[].customFields[].name

String

Custom field name

[]

[].customFields[].value

String

Custom field value

[]

[].owner

String

Certificate owner

[Must be a well-formed email address, Maximum length is 128 characters or can be empty]

[].backendCertId

String

Backend certificate identifier

[Maximum length is 255 characters or can be empty]

[].cert

String

DER (Base64) certificate

[Must not be empty]

[].csr

String

DER (Base64) Certificate Signing Request

[]

[].comments

String

Additional comments

[Maximum length is 1024 characters or can be empty]

[].force

Boolean

Force alter editable certificate fields event if certificate is already exists.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/device/v1/import' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer1603' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1603' \
+    -d '[{"orgID":940,"customFields":[{"name":"testName","value":"testValue"}],"owner":"admin@requester.com","backendCertId":"1234567890DFa","cert":"MIIHHjCCBgagAwIBAgIQDhG71w1UtxDQxvVAtrUspDANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xNjA1MjEwMDAwMDBaFw0xOTA4MTQxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJOWTERMA8GA1UEBxMITmV3IFlvcmsxHTAbBgNVBAoTFFN0YWNrIEV4Y2hhbmdlLCBJbmMuMRwwGgYDVQQDDBMqLnN0YWNrZXhjaGFuZ2UuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr0YDzscT5i6T2FaRsTGNCiLB8OtPXu8N9iAyuaROh/nS0kRRsN8wUMk1TmgZhPuYM6oFS377V8W2LqhLBMrPXi7lnhvKt2DFWCyw38RrDbEsM5dzVGErmhux3F0QqcTI92zjVW61DmE7NSQLiR4yonVpTpdAaO4jSPJxn8d+4p1sIlU2JGSk8LZSWFqaROc7KtXtlWP4HahNRZtdwvL5dIEGGNWx+7B+XVAfY1ygc/UisldkA+a3D2+3WAtXgFZRZZ/1CWFjKWJNMAI6ZBAtlbgSNgRYxdcdleIhPLCzkzWysfltfiBmsmgz6VCoFR4KgJo8Gd3MeTWojBthM10SLwIDAQABo4IDuDCCA7QwHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFFrBQmPCYhOznZSEqjIeF8tto4Z7MIIB6AYDVR0RBIIB3zCCAduCEyouc3RhY2tleGNoYW5nZS5jb22CEXN0YWNrb3ZlcmZsb3cuY29tghMqLnN0YWNrb3ZlcmZsb3cuY29tgg1zdGFja2F1dGguY29tggtzc3RhdGljLm5ldIINKi5zc3RhdGljLm5ldIIPc2VydmVyZmF1bHQuY29tghEqLnNlcnZlcmZhdWx0LmNvbYINc3VwZXJ1c2VyLmNvbYIPKi5zdXBlcnVzZXIuY29tgg1zdGFja2FwcHMuY29tghRvcGVuaWQuc3RhY2thdXRoLmNvbYIRc3RhY2tleGNoYW5nZS5jb22CGCoubWV0YS5zdGFja2V4Y2hhbmdlLmNvbYIWbWV0YS5zdGFja2V4Y2hhbmdlLmNvbYIQbWF0aG92ZXJmbG93Lm5ldIISKi5tYXRob3ZlcmZsb3cubmV0gg1hc2t1YnVudHUuY29tgg8qLmFza3VidW50dS5jb22CEXN0YWNrc25pcHBldHMubmV0ghIqLmJsb2dvdmVyZmxvdy5jb22CEGJsb2dvdmVyZmxvdy5jb22CGCoubWV0YS5zdGFja292ZXJmbG93LmNvbYIVKi5zdGFja292ZXJmbG93LmVtYWlsghNzdGFja292ZXJmbG93LmVtYWlsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc1LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc1LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAAzJAMGSdKoX1frdqNlNiXu8Gcbsm/DxWMXpcTXlZn8s+/qQQoc+/3o0CK3C8/j9n5DmsYa88P6Ntt5ysDs+b0ynXFva4CAEyKaoPM4SIpOjwfWBRSUOqAIkQO2/LhKBwT/EnpaIHIKGnI0UdXLQoDfkMDg6mgJsEBsKdKF5EfEX7iU3NO5xVJPJE8/R0btLAdYwxB9S6fSpCXGe2HqQD101O/7/4MWNdFSbfdDSFcn5oEm+idimrqiNrF5knmuJy4qPBkL7thNuGK6rvYCFZJM03ZEZhkQmn2jG/7LgjfwZmvfcITeADCpylf88bL+lf+vxe6cCl9CyqWgBDpsIxpE=","csr":"MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCY24xDzANBgNVBAgTBmJlaWppbjEQMA4GA1UEBxMHYmVpamluZzEPMA0GA1UEChMGQ09NT0RPMRAwDgYDVQQLEwdkZXZlbG9wMREwDwYDVQQDDAgqLmNtLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxrVE6cqSTe+jOsyYjBNw+5uZeDdu37bRgw6qQo2uSFhOhXyhsxcb0zaitpjNYLsEc4fp0YzNYrqzmIHK7HpgHgg9N9CVr0m2O/RlV761s257expajU1vYzVDIt/levLkOJe96++tOFOQ+6hrFnI2YWKxLdE+X0F7tGrDgkV2xXhW7qbw32C2kRyui3KvgoJ0Mwtwe0Gp6VVN61oNoinf5F/O8MGMFmM4TaRgSTcvWIJvrfuMTmHi9S918LfQRrFGfDKNX49iS8oWT7SVBmLxjcEqIsTfCFo9rg/aP8elS3kRFBH8fTNUPjcOCa/Km6JoIM4C/KEro6uraXAbl+QhMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQBvyheU7vn+VCQJz8OHVD2r9c79KETEeaTMIvnTjGECd3RlXXErcFxuvFJYtTyiNZwzyRi7Q4IBp8g41UYRsBsMim0ioQdW9cIIMMn0oY7oAuQt6eM77iOd/bWhpGAPKe6rG8vadA6nF+hPIPEkqIlfWYNc/ZarvXr2UPNmYdv/skDi9PQUlzB1xOWQUO3Li+QYZWuE3UjLDNCoh5uTY5UMn/K+Ej8fDDz4mc4zZQQf3mASZcMEv75pqfEiRY1zUUPLLT5vUZ5yh32DG8mm+X5Gkr1xQNYGAUymxTdG2ct2t3xxLjGmRABxPvGNIrIefboyLma9Yd0GBOtrexsNzbUI","comments":"Test comments","force":true}]'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of certificates

[].cert

Object

Device Certificate information

[].cert.id

Number

Device Certificate ID

[].cert.subject

String

Device Certificate Subject

[].cert.serialNumber

String

Device Certificate Serial Number

[].created

Boolean

Whether certificate been created or not (it could already exist)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 164
+
+[{"cert":{"id":80,"subject":"CN=*.stackexchange.com,O=Stack Exchange, Inc.,L=New York,ST=NY,C=US","serialNumber":"E11BBD70D54B710D0C6F540B6B52CA4"},"created":true}]
+
+
+
+
+

The response array element can be error message:

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[].errorMessage

String

Error message

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 59
+
+[{"errorMessage":"Custom field cannot be found: testName"}]
+
+
+
+
+
+
+
+
+

Code Signing Certificates

+
+
+

Used to perform operations on code signing certificates.

+
+
+

Manage code signing certificate

+
+

Import code signing certificates to SCM

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

[]

Array

Certificates to import

Should not be empty, maximum size is 128

[].orgID

Number

Organization ID

[Must be at least 1, Must not be null]

[].customFields

Array

List of custom certificate fields

[]

[].customFields[].name

String

Custom field name

[]

[].customFields[].value

String

Custom field value

[]

[].backendCertId

String

Backend certificate identifier

[Maximum length is 255 characters or can be empty]

[].cert

String

DER (Base64) certificate

[Must not be empty]

[].csr

String

DER (Base64) Certificate Signing Request

[]

[].force

Boolean

Force alter editable certificate fields event if certificate is already exists.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/cscert/v1/import' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer18157' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst18157' \
+    -d '[{"orgID":1990,"customFields":[{"name":"testName","value":"testValue"}],"backendCertId":"1234567890DFa","cert":"MIIEKDCCBBKgAwIBAgIRALdTZsH0yQtzU+E3X0Y5xDYwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE+MDwGA1UEAxM1U2VjdGlnbyBSU0EgQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0EwHhcNMjQwNTE2MDAwMDAwWhcNMjUwNTE2MjM1OTU5WjAnMSUwIwYJKoZIhvcNAQkBFhZzb21lb25lbGlrZXVAY2NtcWEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApSh7RPQW7YHv3FmAFq/vySdF+1Zt0XkJk7p3xBuJ/cUzeIL6sqTx7tOZgsPxM97a+fd/UZ731/xSRgM/7x2rdhrZkmWkziyZfFPZE2/2wkicfRPFvdC4OhqNVgSLYmZtBJlkBArWX8MeL3ddiqmQqN7kA/Nw6kuJsIOYduTZnpS5vEXLX6v/jJPv4gECHmjfLuV/e5cY18+qgFGvLEEzz9M4R1H4jdL+sl9xh7LG2AIaERcFJCkQ0YCT4JUU/bKtPNruvBTgE+Tua4tvtr/Akzt2kJOgklzTpkoCkv4EzgYsXyKVGJQjcd268oVMgNWTAMuCnPmDkwhyX7FkcGzudQIDAQABo4IB3zCCAdswHwYDVR0jBBgwFoAUCcDy/AvalNtf/ivfqJlCz8ngrQAwHQYDVR0OBBYEFBrcCXeEnSfJ3XpxwU2GcptYkcWeMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMEBggrBgEFBQcDAjBQBgNVHSAESTBHMDoGDCsGAQQBsjEBAgEKATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3NlY3RpZ28uY29tL1NNSU1FQ1BTMAkGB2eBDAEFAQIwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ2xpZW50QXV0aGVudGljYXRpb25hbmRTZWN1cmVFbWFpbENBLmNybDCBigYIKwYBBQUHAQEEfjB8MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3VyZUVtYWlsQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAhBgNVHREEGjAYgRZzb21lb25lbGlrZXVAY2NtcWEuY29tMA0GCSqGSIb3DQEBCwUAAwEA","csr":"MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCY24xDzANBgNVBAgTBmJlaWppbjEQMA4GA1UEBxMHYmVpamluZzEPMA0GA1UEChMGQ09NT0RPMRAwDgYDVQQLEwdkZXZlbG9wMREwDwYDVQQDDAgqLmNtLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxrVE6cqSTe+jOsyYjBNw+5uZeDdu37bRgw6qQo2uSFhOhXyhsxcb0zaitpjNYLsEc4fp0YzNYrqzmIHK7HpgHgg9N9CVr0m2O/RlV761s257expajU1vYzVDIt/levLkOJe96++tOFOQ+6hrFnI2YWKxLdE+X0F7tGrDgkV2xXhW7qbw32C2kRyui3KvgoJ0Mwtwe0Gp6VVN61oNoinf5F/O8MGMFmM4TaRgSTcvWIJvrfuMTmHi9S918LfQRrFGfDKNX49iS8oWT7SVBmLxjcEqIsTfCFo9rg/aP8elS3kRFBH8fTNUPjcOCa/Km6JoIM4C/KEro6uraXAbl+QhMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQBvyheU7vn+VCQJz8OHVD2r9c79KETEeaTMIvnTjGECd3RlXXErcFxuvFJYtTyiNZwzyRi7Q4IBp8g41UYRsBsMim0ioQdW9cIIMMn0oY7oAuQt6eM77iOd/bWhpGAPKe6rG8vadA6nF+hPIPEkqIlfWYNc/ZarvXr2UPNmYdv/skDi9PQUlzB1xOWQUO3Li+QYZWuE3UjLDNCoh5uTY5UMn/K+Ej8fDDz4mc4zZQQf3mASZcMEv75pqfEiRY1zUUPLLT5vUZ5yh32DG8mm+X5Gkr1xQNYGAUymxTdG2ct2t3xxLjGmRABxPvGNIrIefboyLma9Yd0GBOtrexsNzbUI","force":true}]'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of certificates

[].cert

Object

Code Sign Certificate information

[].cert.id

Number

Code Sign Certificate ID

[].cert.subject

String

Code Sign Certificate Subject

[].cert.serialNumber

String

Code Sign Certificate Serial Number

[].created

Boolean

Whether certificate been created or not (it could already exist)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 122
+
+[{"cert":{"id":59,"subject":"E=someonelikeu@ccmqa.com","serialNumber":"B75366C1F4C90B7353E1375F4639C436"},"created":true}]
+
+
+
+
+
+

Manual Revoke code signing certificate by Id or serial number + issuer

+
+

Mark certificate as revoked. The certificate is not revoked on CA side.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

certId

Number

Certificate ID. Required if serialNumber and issuer are not provided.

Must be present if serialNumber and issuer are not provided

serialNumber

Number

Certificate serial number. Required if certId is not provided (used together with issuer).

Must be present with issuer if certId is not provided

issuer

Number

Certificate issuer. Required if certId is not provided (used together with serialNumber).

Must be present with serialNumber if certId is not provided

revokeDate

String

Certificate revoke date

[]

reasonCode

Number

Revocation reason code to be put to CRL (Mozilla Root Store Policy 2.8 section 6.1.1)

+

Reason code (unspecified (0), + keyCompromise (1), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5))

[Allowed ranges 0,1 and 3-5]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/cscert/v1/revoke/manual' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer18169' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst18169' \
+    -d '{"certId":62,"serialNumber":null,"issuer":null,"revokeDate":"2025-06-10T00:00:00Z","reasonCode":4}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+

The response array element can be error message:

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[].errorMessage

String

Error message

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 50
+
+[{"errorMessage":"Organization ''2'' not found."}]
+
+
+
+
+
+
+
+
+

Code Signing on Demand - Deprecated

+
+
+

The Code Signing on Demand (CSoD) API integrates the CSoD service and automation systems (such as Jenkins, TeamCity, Puppet, PerlScript) to provide an end-to-end, automated code signing platform.

+
+
+

Code signing requests are submitted by developers and approved by administrators. The code signing request must first be created, the files uploaded and the request submitted. The request needs to be approved by an administrator. Once approved, the request is completed automatically and the digitally signed files can be downloaded.

+
+
+

In addition to complete files it is possible to just sign hashes. Place the hash in a file with an md5 or sha extension and specify the HASH_SUM signing type when creating the request.

+
+
+

Developer API

+
+

A developer is a special type of user allowed to use the CsoD service to digitally sign files. These API methods require the Developer Login authentication style.

+
+
+

Create code signing request

+
+

The code signing request must first be created by a developer. The creation returns a request ID and an URL to upload the file to be signed.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationId

Number

Organization ID

version

String

A free form field that can be used to provide file verson information if required

Should not be empty

algorithms

String

Hashing algorithm to use. Multiple comma separated values are possible if the file signing type supports it

Supported values are: MD5, SHA1, SHA256, SHA384, SHA512

signingType

String

Type of file(s) to sign. All uploaded files must be of the same type

Supported values are: MICROSOFT_AUTHENTICODE, JAVA, MICROSOFT_OFFICE_AND_VBA, WINDOWS_PHONE_AND_XBOX, ANDROID, HASH_SUM, POWERSHELL

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

requestId

Number

ID for created request

uploadUrl

String

URL to upload files for signing

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/developer' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'email: test@email' \
+    -H 'password: 123' \
+    -H 'customerUri: cst20386' \
+    -d '{"organizationId":2762,"version":"1","algorithms":"sha384","signingType":"java"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 96
+
+{"requestId":5,"uploadUrl":"https://host:123/path?token=9NC87HU4RM044AINI0DVG84UA8&requestId=5"}
+
+
+
+
+
Additional notes
+
+

Certificate Manager 19.10 contains a bug in that the uploadUrl response field is incorrect. The URL needs to have the requestId added as a URL parameter. Look at the Example response above.

+
+
+
+
+

Upload files

+
+

The files to be digitally signed must be uploaded to the URL returned when the code signing request was created. The upload takes the form of a POST with a multipart/form-data content type. If uploading multiple files, the keys just need to be unique, i.e. file1, file2.

+
+
+
Example request
+
+
+
$ curl -F 'file1=@filename' https://agenthost/path?token=L1P1J62D3ALTVB67M511T5CL73&requestId=5
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
Additional Notes
+
+

The hosted code signing agent by default will use a self-signed certificate so the upload may require extra handling. For example if using curl you can specify the --insecure flag.

+
+
+
+
+

Submit signing request

+
+

After the files have been uploaded the signing request is submitted. The request must then be approved by before it is completed. Requests are approved by an administrator.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

requestId

Number

Request ID returned when request created

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/developer' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'email: test@email' \
+    -H 'password: 123' \
+    -H 'customerUri: cst20413' \
+    -d '{"requestId":1}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Get code signing request count

+
+

Enables the developer to get the number of code signing requests created by them.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

count

Number

Requests count

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/developer/count' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'email: test@email' \
+    -H 'password: 123' \
+    -H 'customerUri: cst20383'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 11
+
+{"count":1}
+
+
+
+
+
+

Get list of submitted requests

+
+

Enables the developer to get the code signing requests IDs created by them.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of request IDs

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/developer/?size=1&position=10' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'email: test@email' \
+    -H 'password: 123' \
+    -H 'customerUri: cst20410'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 3
+
+[2]
+
+
+
+
+
+

Get code signing request details

+
+

Enables the developer to get the code signing requests IDs created by them.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

developerEmail

String

Developer email address

organization

String

Organization name

department

String

Department name. Optional

approver

String

Name of the person who approved operation

version

String

Value provided when creating request

signingService

String

Type of file(s), possible values are: MICROSOFT_AUTHENTICODE, JAVA, MICROSOFT_OFFICE_AND_VBA, WINDOWS_PHONE_AND_XBOX, ANDROID, HASH_SUM, POWERSHELL

created

String

Creation date

state

String

State of request, posible values are: INIT, CREATED, IN_PROGRESS, DECLINED, SIGNED, EXPIRED, FAILED

digestAlgorithms[]

Array

Array of applied hash algorithms

files[]

Array

Array of signed files

files[].name

String

File name

files[].downloadUrl

String

URL to download the digitally signed file from. The process of downloading does involve a redirect to the code signing agent

files[].size

Number

File size

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/developer/1' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'email: test@email' \
+    -H 'password: 123' \
+    -H 'customerUri: cst20404'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 358
+
+{"developerEmail":"test@email","organization":"org4Test","approver":"test ","version":"1","digestAlgorithms":["SHA256"],"signingService":"MICROSOFT_AUTHENTICODE","created":"08/15/2025 09:05:55 GMT","state":"SIGNED","files":[{"name":"test.msi","downloadUrl":"https://cert-manager.com/customer/cst20404/csfile/f337c957-3bb1-43d3-a755-69dced2edeb3","size":10}]}
+
+
+
+
+
+
+

Administrator API

+
+

An administrator is a Certificate Manager user with privileges to approve code signing requests.

+
+
+

Approve code signing request

+
+

Enables the administrators to permit execution of the developer’s code signing request.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

requestId

Number

Request ID to be approved

comment

String

Short message about approval

None

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/admin/approve' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20374' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20374' \
+    -d '{"requestId":1,"comment":"Test"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Decline code signing request

+
+

Enables the administrators to decline execution of the developer’s code signing request.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

requestId

Number

Request ID to be declined

comment

String

Short message about decline

None

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/admin/decline' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20392' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20392' \
+    -d '{"requestId":1,"comment":"Test"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Get code signing request count

+
+

Enables the administrator to get the number of the code signing requests submitted and assigned to the organization(s) or department(s) that are delegated to them.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

count

Number

Requests count

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/admin/count' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20380' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20380'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 11
+
+{"count":2}
+
+
+
+
+
+

Get list of submitted requests

+
+

Enables the administrator to get the code signing requests IDs submitted and assigned to the organization(s) or department(s) that are delegated to them.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of request IDs

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/admin/?size=1&position=10' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20407' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20407'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 5
+
+[2,3]
+
+
+
+
+
+

Get code signing request details

+
+

Enables the administrator to get the code signing request details by its ID.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

developerEmail

String

Developer email address

organization

String

Organization name

department

String

Department name. Optional

approver

String

Name of the person who approved operation

version

String

Value provided when creating request

signingService

String

Type of file(s), possible values are: MICROSOFT_AUTHENTICODE, JAVA, MICROSOFT_OFFICE_AND_VBA, WINDOWS_PHONE_AND_XBOX, ANDROID, HASH_SUM, POWERSHELL

created

String

Creation date

state

String

State of request, posible values are: INIT, CREATED, IN_PROGRESS, DECLINED, SIGNED, EXPIRED, FAILED

digestAlgorithms[]

Array

Array of applied hash algorithms

files[]

Array

Array of signed files

files[].name

String

File name

files[].downloadUrl

String

URL to download the digitally signed file from. The process of downloading does involve a redirect to the code signing agent

files[].size

Number

File size

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/csod/v1/requests/admin/1' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20401' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20401'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 358
+
+{"developerEmail":"test@email","organization":"org4Test","approver":"test ","version":"1","digestAlgorithms":["SHA256"],"signingService":"MICROSOFT_AUTHENTICODE","created":"08/15/2025 09:05:55 GMT","state":"SIGNED","files":[{"name":"test.msi","downloadUrl":"https://cert-manager.com/customer/cst20401/csfile/f337c957-3bb1-43d3-a755-69dced2edeb3","size":10}]}
+
+
+
+
+
+
+
+
+

Domain Control Validation

+
+
+

Any domain added to SCM must pass Domain Control Validation (DCV) before public certificates can be issued to it. DCV is a procedure of validation of the applicant’s control of the domain which needs to appear in the subject of the certificate.

+
+
+

View domain control validations

+
+

List domain control validations

+
+

List all domain validations that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

domain

Domain

org

Organization ID

department

Department ID

dcvStatus

DCV Status

orderStatus

DCV Order status

expiresIn

Expires in (days)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation?size=10&position=0&org=&department=&domain=ccmqa.com&expiresIn=&dcvStatus=&orderStatus=' -i -X GET \
+    -H 'login: admin_customer20512' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20512' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of DCV domains

[].domain

String

Domain

[].dcvStatus

String

DCV Status

[].dcvOrderStatus

String

DCV Order status

[].dcvOrderMethod

String

DCV Order method. Values: [EMAIL, CNAME, HTTP, HTTPS, AUTO, TXT]

[].dcvMethod

String

DCV Method

[].expirationDate

String

DCV Expiration date

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 380
+
+[ {
+  "domain" : "ccmqa.com",
+  "dcvStatus" : "VALIDATED",
+  "dcvMethod" : "EMAIL",
+  "dcvOrderStatus" : "NOT_INITIATED",
+  "dcvOrderMethod" : "EMAIL",
+  "expirationDate" : "2025-08-16"
+}, {
+  "domain" : "www.ccmqa.com",
+  "dcvStatus" : "VALIDATED",
+  "dcvMethod" : "EMAIL",
+  "dcvOrderStatus" : "NOT_INITIATED",
+  "dcvOrderMethod" : "EMAIL",
+  "expirationDate" : "2025-08-16"
+} ]
+
+
+
+
+
+

Get domain control validation details

+
+

Get domain validation details. The V2 API provides more information about the domain validation and is the preferred version.

+
+
+

V2

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain which status is requested

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v2/validation/status' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20471' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20471' \
+    -H 'Accept: application/json' \
+    -d '{
+  "domain" : "example.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

String

Validation status

validationDate

String

Validation date

expirationDate

String

Validation expiration date

orderStatus

String

Validation order status

orderMode

String

Validation order mode. Possible values: [EMAIL, CNAME, HTTP, HTTPS, AUTO, TXT]

url

String

HTTP(s) validation. URL to the validation txt file in the "/.well-known/pki-validation" directory of the HTTP server

firstLine

String

HTTP(s) validation. Validation txt file content: first line

secondLine

String

HTTP(s) validation. Validation txt file content: second line

host

String

DNS validation record host value

point

String

DNS validation record point value

validationEmail

String

Email validation recipient

emailValidationReferenceNumber

String

Email validation reference number

orderBackendId

String

Validation order backend ID

submittedDate

String

Validation order submission date(only for submitted orders)

lastCheck

String

Time of last check(only for submitted orders)

nextCheck

String

Time of the scheduled next check(only for submitted orders)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 518
+
+{
+  "status" : "EXPIRED",
+  "validationDate" : "2024-08-15",
+  "expirationDate" : "2025-08-05",
+  "orderStatus" : "SUBMITTED",
+  "orderMode" : "HTTP",
+  "url" : "http://example.com/.well-known/pki-validation/328E41AAD15613A48AF48807291C2D63.txt",
+  "firstLine" : "b38777ecc4777069142a0e75c16de63716da04aafd74f8b28d284cbbfc131660",
+  "secondLine" : "sectigo.com",
+  "orderBackendId" : "99887766",
+  "submittedDate" : "2025-08-15",
+  "lastCheck" : "2025-08-15T08:20:42.718Z",
+  "nextCheck" : "2025-08-15T10:20:42.718Z"
+}
+
+
+
+
+

V1 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/status' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20502' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20502' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

String

Validation status

validationDate

String

Validation date

expirationDate

String

Validation expiration date

orderStatus

String

Validation order status

orderMode

String

Validation order mode. Possible values: [EMAIL, CNAME, HTTP, HTTPS, AUTO, TXT]

url

String

HTTP(s) validation. URL to the validation txt file in the "/.well-known/pki-validation" directory of the HTTP server

firstLine

String

HTTP(s) validation. Validation txt file content: first line

secondLine

String

HTTP(s) validation. Validation txt file content: second line

host

String

DNS validation record host value

point

String

DNS validation record point value

validationEmail

String

Email validation recipient

emailValidationReferenceNumber

String

Email validation reference number

orderBackendId

String

Validation order backend ID

submittedDate

String

Validation order submission date(only for submitted orders)

lastCheck

String

Time of last check(only for submitted orders)

nextCheck

String

Time of the scheduled next check(only for submitted orders)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 133
+
+{
+  "status" : "VALIDATED",
+  "validationDate" : "2024-08-16",
+  "expirationDate" : "2025-08-16",
+  "orderStatus" : "NOT_INITIATED"
+}
+
+
+
+
+
+

Sync domain control validation details with backend

+
+

Synchronize domain validation details with backend.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/sync?force=true' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20662' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20662' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

String

Validation status

validationDate

String

Validation date

expirationDate

String

Validation expiration date

orderStatus

String

Validation order status

orderMode

String

Validation order mode. Possible values: [EMAIL, CNAME, HTTP, HTTPS, AUTO, TXT]

url

String

HTTP(s) validation. URL to the validation txt file in the "/.well-known/pki-validation" directory of the HTTP server

firstLine

String

HTTP(s) validation. Validation txt file content: first line

secondLine

String

HTTP(s) validation. Validation txt file content: second line

host

String

DNS validation record host value

point

String

DNS validation record point value

validationEmail

String

Email validation recipient

emailValidationReferenceNumber

String

Email validation reference number

orderBackendId

String

Validation order backend ID

submittedDate

String

Validation order submission date(only for submitted orders)

lastCheck

String

Time of last check(only for submitted orders)

nextCheck

String

Time of the scheduled next check(only for submitted orders)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 168
+
+{
+  "status" : "NOT_VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "orderMode" : "EMAIL",
+  "emailValidationReferenceNumber" : "1099190539",
+  "orderBackendId" : "1234"
+}
+
+
+
+
+
+

Clear domain control validation

+
+

Reset the parameters of a request for DCV and drop domain validation Status and DCV Order Status of the domain to the initial values.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/clear' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20487' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20487' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 135
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "NOT_INITIATED",
+  "message" : "DCV status: VALIDATED; DCV order status: NOT_INITIATED"
+}
+
+
+
+
+
+

Delete domain control validation

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to remove validation from

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/delete' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20497' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20497' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+

Validate domain

+
+

Method HTTP

+
+
Start domain control validation HTTP
+
+

Start Domain Control Validation using HTTP method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/start/domain/http' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20637' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20637' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

url

String

URL

firstLine

String

First line

secondLine

String

Second line

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 212
+
+{
+  "url" : "http://ccmqa.com/.well-known/pki-validation/3223E4ECBBA675CF826EF3633AF97ACE.txt",
+  "firstLine" : "54e679f20a5476c171bc721bfc51191ea2e8e87b93f0f84f016388e504f67694",
+  "secondLine" : "sectigo.com"
+}
+
+
+
+
+
+
Start domain control validation HTTPS
+
+

Start Domain Control Validation using HTTPS method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/start/domain/https' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20647' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20647' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

url

String

URL

firstLine

String

First line

secondLine

String

Second line

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 213
+
+{
+  "url" : "https://ccmqa.com/.well-known/pki-validation/3223E4ECBBA675CF826EF3633AF97ACE.txt",
+  "firstLine" : "54e679f20a5476c171bc721bfc51191ea2e8e87b93f0f84f016388e504f67694",
+  "secondLine" : "sectigo.com"
+}
+
+
+
+
+
+
Submit domain control validation HTTP
+
+

Submit a request for Domain Control Validation using HTTP method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/http' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20637' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20637' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 130
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500"
+}
+
+
+
+
+
+
Submit domain control validation HTTPS
+
+

Submit a request for Domain Control Validation using HTTPS method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/https' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20647' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20647' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 130
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500"
+}
+
+
+
+
+
+
+

Method DNS

+
+
Start domain control validation CName
+
+

Start Domain Control Validation using CName method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/start/domain/cname' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20612' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20612' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

host

String

Host

point

String

Point

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 155
+
+{
+  "host" : "_3223e4ecbba675cf826ef3633af97ace.ccmqa.com.",
+  "point" : "54e679f20a5476c171bc721bfc51191e.a2e8e87b93f0f84f016388e504f67694.sectigo.com."
+}
+
+
+
+
+
+
Submit domain control validation CName
+
+

Submit a request for Domain Control Validation using CName method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/cname' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20612' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20612' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 130
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500"
+}
+
+
+
+
+
+
Submit domain control validation CName using DNS Connector
+
+

Submit a request for Domain Control Validation using CName method in an automated manner. See DNS Connector API for more details.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

dnsAgentUUID

String

Domain agent UUID

[]

dnsProviderName

String

DNS provider name

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/cname' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20607' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20607' \
+    -d '{
+  "dnsAgentUUID" : "975f32e1ca7942bb8c0a1cc2f80d802f",
+  "dnsProviderName" : "cloudflare",
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 134
+
+{
+  "status" : "NOT_VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500"
+}
+
+
+
+
+
+
Start domain control validation TXT
+
+

Start request is not supported by the API. Use submit directly.

+
+
+
+
Submit domain control validation using TXT record
+
+

Submit a request for Domain Control Validation using TXT method. +Use information from the response to create a DNS TXT record. (i.e. _pki-validation.<domain name>. TXT <validation code>)

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/txt' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20657' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20657' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

host

String

DNS TXT record host

point

String

DNS TXT record point

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 220
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500",
+  "host" : "_pki-validation.ccmqa.com.",
+  "point" : "E-_(Nw4eH\" v{zU4m*'zr]!4Np4Ka4aj"
+}
+
+
+
+
+
+
+

Method Email

+
+
Start domain control validation email
+
+

Retrieve emails that could be used for Domain Control Validation.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Size must be between 3 and 255 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/start/domain/email' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20622' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20622' \
+    -d '{
+  "domain" : "ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

emails[]

Array

Array of e-mails

dcvEmails

Array

List of e-mails for each domain

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 486
+
+{
+  "emails" : [ "webmaster@ccmqa.com", "administrator@ccmqa.com", "hostmaster@ccmqa.com", "dns.txt@sectigo.com", "domain.admin@sectigo.com", "admin@ccmqa.com", "postmaster@ccmqa.com" ],
+  "dcvEmails" : [ {
+    "domainName" : "ccmqa.com",
+    "whoisEmails" : [ "domain.admin@sectigo.com" ],
+    "adminEmails" : [ "admin@ccmqa.com", "administrator@ccmqa.com", "hostmaster@ccmqa.com", "postmaster@ccmqa.com", "webmaster@ccmqa.com" ],
+    "dnsTxtEmails" : [ "dns.txt@sectigo.com" ]
+  } ]
+}
+
+
+
+
+
+
Start domain control validation email bulk
+
+

Retrieve emails that could be used for Domain Control Validation.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains

Array

Domain lists to receive DCV e-mails

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/start/domain/email' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20582' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20582' \
+    -d '{
+  "domains" : [ "ccmqa.com", "domain.com" ]
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

emails[]

Array

Common emails applicable for bulk DCV

dcvEmails

Array

List of e-mails for each domain

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 654
+
+{
+  "emails" : [ "dns.txt@sectigo.com", "domain.admin@sectigo.com" ],
+  "dcvEmails" : [ {
+    "domainName" : "ccmqa.com",
+    "whoisEmails" : [ "domain.admin@sectigo.com" ],
+    "adminEmails" : [ "admin@ccmqa.com", "administrator@ccmqa.com", "hostmaster@ccmqa.com", "postmaster@ccmqa.com", "webmaster@ccmqa.com" ],
+    "dnsTxtEmails" : [ "dns.txt@sectigo.com" ]
+  }, {
+    "domainName" : "domain.com",
+    "whoisEmails" : [ "domain.admin@sectigo.com" ],
+    "adminEmails" : [ "admin@domain.com", "administrator@domain.com", "hostmaster@domain.com", "postmaster@domain.com", "webmaster@domain.com" ],
+    "dnsTxtEmails" : [ "dns.txt@sectigo.com" ]
+  } ]
+}
+
+
+
+
+
+
Submit domain control validation email
+
+

Submit a request for Domain Control Validation using Email method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domain

String

Domain to validate

[Must not be empty, Maximum length is 255 characters or can be empty]

email

String

E-mail

[Must be a well-formed email address, Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit/domain/email' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20622' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20622' \
+    -d '{
+  "domain" : "ccmqa.com",
+  "email" : "email@ccmqa.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

orderStatus

String

Order status

message

String

Message

status

String

Status

orderBackendId

String

Validation order backend ID

emailValidationReferenceNumber

String

Email validation reference number

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 181
+
+{
+  "status" : "VALIDATED",
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500",
+  "emailValidationReferenceNumber" : "1099190539"
+}
+
+
+
+
+
+
Submit bulk domain control validation email
+
+

Submit a request for Domain Control Validation using Email method.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains

Array

Domains to validate

[Must not be empty]

email

String

DCV email suitable for validating all provided domains. Refer to /api/validation/start/domain/email for more details

[Must be a well-formed email address, Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/dcv/v1/validation/submit-bulk/domain/email' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20632' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20632' \
+    -d '{
+  "domains" : [ "ccmqa.com", "domain.com" ],
+  "email" : "domain.admin@sectigo.com"
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

message

String

Message

orderStatus

String

Validation order status

orderBackendId

String

Validation order backend ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 104
+
+{
+  "orderStatus" : "SUBMITTED",
+  "message" : "Submitted successfully",
+  "orderBackendId" : "100500"
+}
+
+
+
+
+
+
+
+
+
+

Custom Fields

+
+
+

Custom fields allow storage of custom metadata with certificates.

+
+
+

View custom fields

+
+

List custom fields

+
+

List all custom fields. Includes complete details.

+
+
+

V2

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2' -i -X GET \
+    -H 'login: admin_customer20705' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20705' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of custom fields

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatories

Array

List of access methods for which this field is mandatory

[].certType

String

Custom field certificate type

[].state

String

State

[].input.type

String

Input type

[].input.options

Array

Input field options (for 'TEXT_OPTION' type only)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 189
+
+[{"id":149,"name":"Test field","certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_OPTION","options":["option1","option2"]},"mandatories":["REST_API","SOAP_API","ADMIN_UI","WEB_FORM"]}]
+
+
+
+
+

V1 - Deprecated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v1' -i -X GET \
+    -H 'login: admin_customer20681' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20681' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of custom fields

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatory

Boolean

Custom field mandatory attribute

[].certType

String

Custom field certificate type

[].state

String

State

[].input

Object

Input field properties

[].input.type

String

Input field type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 119
+
+[{"id":141,"name":"Test field","mandatory":true,"certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_SINGLE_LINE"}}]
+
+
+
+
+
+

List custom fields by certificate type

+
+

List all custom fields filtered by certificate type. Includes complete details.

+
+
+

V2

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

certType

Certificate type. Possible values: [SSL, SMIME, CodeSign, Device]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2/?certType=SSL' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20708' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20708'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatories

Array

List of access methods for which this field is mandatory

[].certType

String

Custom field certificate type

[].state

String

State

[].input.type

String

Input type

[].input.options

Array

Input field options (for 'TEXT_OPTION' type only)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 189
+
+[{"id":150,"name":"Test field","certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_OPTION","options":["option1","option2"]},"mandatories":["REST_API","SOAP_API","ADMIN_UI","WEB_FORM"]}]
+
+
+
+
+

V1 - Deprecated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v1/ssl' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20684' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20684'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

Number

Custom field ID

[].name

String

Custom field name

[].mandatory

Boolean

Custom field mandatory attribute

[].certType

String

Custom field certificate type

[].state

String

State

[].input

Object

Input field properties

[].input.type

String

Input field type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 119
+
+[{"id":142,"name":"Test field","mandatory":true,"certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_SINGLE_LINE"}}]
+
+
+
+
+
+

Get custom field details

+
+

Get custom field details.

+
+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/customField/v2/{id}
ParameterDescription

id

ID of custom field whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2/148' -i -X GET \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20702' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20702'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Custom field ID

name

String

Custom field name

mandatories

Array

List of access methods for which this field is mandatory

certType

String

Custom field certificate type

state

String

State

input.type

String

Input type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 154
+
+{"id":148,"name":"test","certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_SINGLE_LINE"},"mandatories":["REST_API","SOAP_API","ADMIN_UI","WEB_FORM"]}
+
+
+
+
+
+
+

Manage custom fields

+
+

Create custom field

+
+

Create the custom field for a particular type of certificate.

+
+
+

V2

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Custom field name

[Must not be blank, Maximum length is 256 characters or can be empty]

mandatories

Array

List of access methods for which this field is mandatory

Possible values: ADMIN_UI, REST_API, SOAP_API, WEB_FORM

certType

String

Custom field certificate type

Possible values: ssl, smime, device, codesign

state

String

State

[]

input.type

String

Input type

Input type. Allowed values: [TEXT_SINGLE_LINE, TEXT_MULTI_LINE, EMAIL, NUMBER, TEXT_OPTION, DATE]

input.options

Array

Input options (for 'TEXT_OPTION' type only)

[Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20693' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20693' \
+    -d '  {"name":"test","certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_OPTION", "options": ["Option 1", "Option2"]},
+                  "mandatories":["ADMIN_UI","REST_API","SOAP_API","WEB_FORM"]}
+'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created custom field

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/customField/v2/145
+
+
+
+
+

V1 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Custom field name

[Must not be blank, Maximum length is 256 characters or can be empty]

mandatory

Boolean

Custom field mandatory attribute

[]

certType

String

Custom field certificate type

Possible values: ssl, smime, device

state

String

State

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v1' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20672' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20672' \
+    -d '  {"name":"test","mandatory":true,"certType":"ssl","state":"ACTIVE"}
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Custom field ID

name

String

Custom field name

mandatory

Boolean

Custom field mandatory attribute

certType

String

Custom field certificate type

state

String

State

input

Object

Input field properties

input.type

String

Input field type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 111
+
+{"id":138,"name":"test","mandatory":true,"certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_SINGLE_LINE"}}
+
+
+
+
+
+

Update custom field

+
+

Update custom field.

+
+
+

V2

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

id

Number

Custom field ID

name

String

Custom field name

[Must not be blank, Maximum length is 256 characters or can be empty]

mandatories

Array

List of access methods for which this field is mandatory

Possible values: ADMIN_UI, REST_API, SOAP_API, WEB_FORM

certType

String

Custom field certificate type

Possible values: ssl, smime, device, codesign

state

String

State

[]

input.type

String

Input type

[]

input.options

Array

Input options (for 'TEXT_OPTION' type only)

[Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20711' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20711' \
+    -d '{
+    "id": 151,
+    "name":"Test field",
+    "certType":"ssl",
+    "state":"ACTIVE",
+    "mandatories":[],
+    "input": {"type": "TEXT_OPTION", "options": ["option1", "option2"]}
+}
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Custom field ID

name

String

Custom field name

mandatories

Array

List of access methods for which this field is mandatory

certType

String

Custom field certificate type

state

String

State

input

Object

Input field properties

input.type

String

Input field type

input.options

Array

Input field options

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 144
+
+{"id":151,"name":"Test field","certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_OPTION","options":["option1","option2"]},"mandatories":[]}
+
+
+
+
+

V1 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

id

Number

Custom field ID

[Must be at least 1]

name

String

Custom field name

[Must not be blank, Maximum length is 256 characters or can be empty]

mandatory

Boolean

Custom field mandatory attribute

[]

certType

String

Custom field certificate type

Possible values: ssl, smime, device

state

String

State

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v1' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20687' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20687' \
+    -d ' {"id":143,"name":"Test field","mandatory":true,"certType":"ssl","state":"ACTIVE"}
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Custom field ID

name

String

Custom field name

mandatory

Boolean

Custom field mandatory attribute

certType

String

Custom field certificate type

state

String

State

input

Object

Input field properties

input.type

String

Input field type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 117
+
+{"id":143,"name":"Test field","mandatory":true,"certType":"ssl","state":"ACTIVE","input":{"type":"TEXT_SINGLE_LINE"}}
+
+
+
+
+
+

Delete custom field

+
+

Delete the custom field which is no longer needed.

+
+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/customField/v2/{id}
ParameterDescription

id

Custom field ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v2/147' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20699' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20699'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/customField/v1/{id}
ParameterDescription

id

Custom field ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/customField/v1/140' -i -X DELETE \
+    -H 'Content-Type: application/json' \
+    -H 'Accept: application/json' \
+    -H 'login: admin_customer20678' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20678'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+
+
+

Discovery

+
+
+

The Discovery API automates frequently performed operations to accelerate certificate discovery for customers with dynamically changing IP ranges.

+
+
+

The 'Tasks' resource contains information about planned discovery scans. A task comprises general information (task name, agent, ranges to scan), assignment rules, scan schedule, and has a 'Status' parameter.

+
+
+

Network Discovery Tasks

+
+

Add network scan task

+
+

Enables administrators to create a scan task for the private and/or public network(s) in search of SSL certificates.

+
+
+

V2 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[]

ranges

Array

Array of ranges

[]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[]

dayOfMonth

Number

Day of month

[]

dayOfWeek

Number

Day of week

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3560' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3560' \
+    -d '{"ranges":[{"address":"134.110.70.147/32","ports":"2"}],"agent":"org4Test73t21","name":"ROSYYVRTRJAGHTSEYPVATBWLZEXYBBUN","certBucketId":"63a804cb-164b-4c08-80d6-757383a6fed5","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

taskId

Number

Task ID

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Content-Type: application/json
+Content-Length: 15
+
+{"taskId":1000}
+
+
+
+
+

V3 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

ranges

Array

Array of ranges

[Must not be empty]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3354' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3354' \
+    -d '{"ranges":[{"address":"128.17.118.232/32","ports":"2"}],"agent":"org4Testkatb9","name":"UGHHRWLCIOBBCYDZJKKHNDPKPUFUWBYU","certBucketId":"a2a8e7ea-73f8-42a4-98f3-16ec54229e42","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created task

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v3/net_task/10000
+
+
+
+
+

V4

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

ranges

Array

Array of ranges

[Must not be empty]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

year

Number

Year

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/net_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer18115' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst18115' \
+    -d '{"ranges":[{"address":"145.170.241.77/32","ports":"2"}],"agent":"org4Testwjw8i","name":"ALTYCNWVPFOHNZDSDTYFFWDDBRSHPNLJ","certBucketId":"c6fd7b18-b60a-4b27-b701-1ce5c097ea1c","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":12,"dayOfMonth":31,"dayOfWeek":7,"year":2049}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created task

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v4/net_task/41708
+
+
+
+
+
+

Update network scan task

+
+

Enables administrators to edit a network scan task.

+
+
+

V2 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

taskId

Number

Task ID

[Must be at least 1]

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

ranges

Array

Array of ranges

[Must not be empty]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3617' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3617' \
+    -d '{"taskId":16420,"ranges":[{"address":"140.107.236.79/32","ports":"0"}],"agent":"org4Test6vs8h","name":"UJQKVBWUBVQQFMYQSHTLGQWTCMUBFMZG","certBucketId":"bf67cb16-c6c7-4a35-a6cb-eaa928d7b8d4","frequency":"Monthly","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V3 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

ranges

Array

Array of ranges

[Must not be empty]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/net_task/{id}
ParameterDescription

id

ID of task whose details are being updated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task/6118' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3357' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3357' \
+    -d '{"ranges":[{"address":"29.205.121.101/32","ports":"3"}],"agent":"org4Test2pmpu","name":"DJTEKQRPINDRRKYGTYJGCUKBSTWYSUQO","certBucketId":"f9e195f5-eab1-4973-bce3-447d053992b5","frequency":"Monthly","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V4

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

ranges

Array

Array of ranges

[Must not be empty]

ranges[].address

String

Range address

ranges[].ports

String

Range port

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

year

Number

Year

[]

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v4/net_task/{id}
ParameterDescription

id

ID of task whose details are being updated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/net_task/43728' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer18148' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst18148' \
+    -d '{"ranges":[{"address":"190.215.110.38/32","ports":"0"}],"agent":"org4Test770f0","name":"ARRUYUSFMFGYYWRQEXDKXITVPWRMGFGK","certBucketId":"fc8a44c2-1c9d-42ed-aa47-b66ec6ba0a44","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":12,"dayOfMonth":31,"dayOfWeek":7,"year":2049}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Get network scan task

+
+

Enables the administrator to get the parameters of a particular task of network scanning which he/she is authorized to view and manage.

+
+
+

V2 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/net_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task/15814' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3605' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3605'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

ranges

Array

Array of ranges

ranges[].address

Array

Range address

ranges[].ports

Array

Range port

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month

dayOfMonth

Number

Day of month

dayOfWeek

Number

Day of week

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 179
+
+{"name":"Discovery task 0","agent":"","ranges":[],"frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":13},"status":"Scan in process"}
+
+
+
+
+

V3 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/net_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task/2684' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3270' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3270'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

ranges

Array

Array of ranges

ranges[].address

Array

Range address

ranges[].ports

Array

Range port

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month

dayOfMonth

Number

Day of month

dayOfWeek

Number

Day of week

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 179
+
+{"name":"Discovery task 0","agent":"","ranges":[],"frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":12},"status":"Scan in process"}
+
+
+
+
+

V4

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v4/net_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/net_task/43526' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer18145' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst18145'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

ranges

Array

Array of ranges

ranges[].address

Array

Range address

ranges[].ports

Array

Range port

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

year

Number

Year

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 179
+
+{"name":"Discovery task 0","agent":"","ranges":[],"frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":15},"status":"Scan in process"}
+
+
+
+
+
+

Get network scan task list

+
+

Enables the administrator to get the list of existing tasks of scanning the network(s) which he/she is authorized to view and manage.

+
+
+

V2 - Deprecated

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Task name

status

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task?size=10&position=0&name=Discovery+task+1&status=IN_PROCESS' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3728' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3728'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of network discovery tasks available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Scan Tasks

[].taskId

Number

Scan Task ID

[].name

String

Name of Scan Task

[].status

String

Scan Task Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 10
+Content-Type: application/json
+Content-Length: 743
+
+[{"taskId":21874,"name":"Discovery task 0","status":"Scan in process"},{"taskId":21875,"name":"Discovery task 1","status":"Scan FAILED"},{"taskId":21876,"name":"Discovery task 2","status":"Scan CANCELED by user"},{"taskId":21877,"name":"Discovery task 3","status":"Scan completed (Successful)"},{"taskId":21878,"name":"Discovery task 4","status":"Scan completed (Partial SUCCESSFUL)"},{"taskId":21879,"name":"Discovery task 5","status":"Scan completed (Processing Result)"},{"taskId":21880,"name":"Discovery task 6","status":null},{"taskId":21881,"name":"Discovery task 7","status":"Scan in process"},{"taskId":21882,"name":"Discovery task 8","status":"Scan FAILED"},{"taskId":21883,"name":"Discovery task 9","status":"Scan CANCELED by user"}]
+
+
+
+
+

V3

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Task name

status

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task?size=10&position=0&name=Discovery+task+1&status=IN_PROCESS' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3342' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3342'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of network discovery tasks available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Scan Tasks

[].taskId

Number

Scan Task ID

[].name

String

Name of Scan Task

[].status

String

Scan Task Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 10
+Content-Type: application/json
+Content-Length: 733
+
+[{"taskId":5310,"name":"Discovery task 0","status":"Scan in process"},{"taskId":5311,"name":"Discovery task 1","status":"Scan FAILED"},{"taskId":5312,"name":"Discovery task 2","status":"Scan CANCELED by user"},{"taskId":5313,"name":"Discovery task 3","status":"Scan completed (Successful)"},{"taskId":5314,"name":"Discovery task 4","status":"Scan completed (Partial SUCCESSFUL)"},{"taskId":5315,"name":"Discovery task 5","status":"Scan completed (Processing Result)"},{"taskId":5316,"name":"Discovery task 6","status":null},{"taskId":5317,"name":"Discovery task 7","status":"Scan in process"},{"taskId":5318,"name":"Discovery task 8","status":"Scan FAILED"},{"taskId":5319,"name":"Discovery task 9","status":"Scan CANCELED by user"}]
+
+
+
+
+
+

Start network scan task

+
+

Enables administrators to start a network(s) scan for a specific task

+
+
+

V2 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/net_task/{taskId}/start
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task/22278/start' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3737' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3737'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V3

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/net_task/{taskId}/start
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task/5714/start' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3351' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3351'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete network scan task

+
+

Enables administrators to delete a specific network scanning task.

+
+
+

V2 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/net_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/net_task/22076' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3731' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3731'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+

V3

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/net_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/net_task/5512' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3345' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3345'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

MS AD Discovery Tasks

+
+

Add MS AD scan task

+
+

Enables administrators to create a scan task in search of SSL certificates.

+
+
+

V2 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[]

dayOfMonth

Number

Day of month

[]

dayOfWeek

Number

Day of week

[]

depth

Number

Max Depth of the Scan

[]

domainDefinition

String

Domains to Scan

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3740' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3740' \
+    -d '{"depth":5,"agent":"e6f738dd-e9ef-46d7-903f-bba4e589f7e6","domainDefinition":"sectigo.com","name":"QKWXRHHDJIAEPNPRHRTWLBNLTTOWFVCD","certBucketId":"0cdfab98-4567-4b73-aefb-d71aac8db7cf","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

taskId

Number

Task ID

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Content-Type: application/json
+Content-Length: 22
+
+{"taskId":-1645617531}
+
+
+
+
+

V3 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

depth

Number

Max Depth of the Scan

[Must be at most 99, Must not be null]

domainDefinition

String

Domains to Scan

[Maximum length is 255 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4200' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4200' \
+    -d '{"depth":5,"agent":"746abec5-8b84-46e5-87ec-4e24e6b8cce6","domainDefinition":"sectigo.com","name":"GYJFIRUNOOOQGZFTZYSHBFHVBVDXDGDM","certBucketId":"5d00c732-50f9-4fe7-a076-3af92f785012","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created task

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v3/ad_task/1819196584
+
+
+
+
+

V4

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

depth

Number

Max Depth of the Scan

[Must be at most 99, Must not be null]

domainDefinition

String

Domains to Scan

[Maximum length is 255 characters or can be empty]

year

Number

Year

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/ad_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3518' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3518' \
+    -d '{"depth":5,"agent":"721aff5b-ef85-4a84-b1d4-d28d813aa118","domainDefinition":"sectigo.com","name":"XXSUMBPKMYOGYMHOLRTCPLXGWSICPSEI","certBucketId":"26aa4db8-f001-4c91-a1eb-1b9a924258e8","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":12,"dayOfMonth":31,"dayOfWeek":7,"year":2049}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created task

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v4/ad_task/10360
+
+
+
+
+
+

Update MS AD scan task

+
+

Enables administrators to edit a ms ad scan task.

+
+
+

V2 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

taskId

Number

Task ID

[Must be at least 1]

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

depth

Number

Max Depth of the Scan

[Must be at most 99, Must not be null]

domainDefinition

String

Domains to Scan

[Maximum length is 255 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3794' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3794' \
+    -d '{"taskId":25712,"depth":2,"agent":"ef5484ea-4043-4297-a06c-22a4d8bd0701","domainDefinition":"sectigo.com","name":"SHWXDUYGHCQXRMWLVFURNHFOBDBPOWMP","certBucketId":"c0291c5d-0eb6-4ede-b3fc-48cffbf1889c","frequency":"Monthly","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V3 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month

[Must be at most 11]

dayOfMonth

Number

Day of month

[Must be at most 30]

dayOfWeek

Number

Day of week

[Must be at most 6]

depth

Number

Max Depth of the Scan

[Must be at most 99, Must not be null]

domainDefinition

String

Domains to Scan

[Maximum length is 255 characters or can be empty]

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/ad_task/{id}
ParameterDescription

id

ID of task whose details are being updated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task/37264' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4203' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4203' \
+    -d '{"depth":2,"agent":"795f6146-eebe-490a-855a-21d0be5401f6","domainDefinition":"sectigo.com","name":"VJNUROJTCAFACSFREVDGWUSKIWRJSZFH","certBucketId":"8af2b615-c7db-49ce-b999-97b02a3e6d47","frequency":"Monthly","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":0,"dayOfMonth":0,"dayOfWeek":0}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V4

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

agent

String

Agent name

[Must not be empty]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

depth

Number

Max Depth of the Scan

[Must be at most 99, Must not be null]

domainDefinition

String

Domains to Scan

[Maximum length is 255 characters or can be empty]

year

Number

Year

[]

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v4/ad_task/{id}
ParameterDescription

id

ID of task whose details are being updated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/ad_task/12784' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3557' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3557' \
+    -d '{"depth":5,"agent":"2a5922dd-153f-42a5-848f-c448b88eadfb","domainDefinition":"sectigo.com","name":"XHWCVWDKWOEWQJMJKJCCKYVBITCCPQZY","certBucketId":"daf285d9-e117-49f1-a0b1-09ed8ab905d1","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":12,"dayOfMonth":31,"dayOfWeek":7,"year":2049}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Get MS AD scan task

+
+

Enables the administrator to get the parameters of a particular task which he/she is authorized to view and manage.

+
+
+

V2 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/ad_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task/25106' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3782' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3782'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month

dayOfMonth

Number

Day of month

dayOfWeek

Number

Day of week

depth

Number

Max Depth of the Scan

domainDefinition

String

Domains to Scan

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 199
+
+{"name":"Discovery task 0","agent":"","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":13},"status":"Scan in process","depth":0,"domainDefinition":""}
+
+
+
+
+

V3 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/ad_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task/33830' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4116' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4116'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month

dayOfMonth

Number

Day of month

dayOfWeek

Number

Day of week

depth

Number

Max Depth of the Scan

domainDefinition

String

Domains to Scan

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 199
+
+{"name":"Discovery task 0","agent":"","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":14},"status":"Scan in process","depth":0,"domainDefinition":""}
+
+
+
+
+

V4

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v4/ad_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v4/ad_task/12582' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3554' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3554'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

agent

String

Agent name

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

depth

Number

Max Depth of the Scan

domainDefinition

String

Domains to Scan

year

Number

Year

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 199
+
+{"name":"Discovery task 0","agent":"","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":13},"status":"Scan in process","depth":0,"domainDefinition":""}
+
+
+
+
+
+

Get MS AD scan task list

+
+

Enables the administrator to get the list of existing tasks of scanning which he/she is authorized to view and manage.

+
+
+

V2 - Deprecated

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Task name

status

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task?size=10&position=0&name=Discovery+task+1&status=IN_PROCESS' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3899' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3899'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of network discovery tasks available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Scan Tasks

[].taskId

Number

Scan Task ID

[].name

String

Name of Scan Task

[].status

String

Scan Task Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 10
+Content-Type: application/json
+Content-Length: 743
+
+[{"taskId":30762,"name":"Discovery task 0","status":"Scan in process"},{"taskId":30763,"name":"Discovery task 1","status":"Scan FAILED"},{"taskId":30764,"name":"Discovery task 2","status":"Scan CANCELED by user"},{"taskId":30765,"name":"Discovery task 3","status":"Scan completed (Successful)"},{"taskId":30766,"name":"Discovery task 4","status":"Scan completed (Partial SUCCESSFUL)"},{"taskId":30767,"name":"Discovery task 5","status":"Scan completed (Processing Result)"},{"taskId":30768,"name":"Discovery task 6","status":null},{"taskId":30769,"name":"Discovery task 7","status":"Scan in process"},{"taskId":30770,"name":"Discovery task 8","status":"Scan FAILED"},{"taskId":30771,"name":"Discovery task 9","status":"Scan CANCELED by user"}]
+
+
+
+
+

V3

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Task name

status

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task?size=10&position=0&name=Discovery+task+1&status=IN_PROCESS' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4188' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4188'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of network discovery tasks available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Scan Tasks

[].taskId

Number

Scan Task ID

[].name

String

Name of Scan Task

[].status

String

Scan Task Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 10
+Content-Type: application/json
+Content-Length: 743
+
+[{"taskId":36456,"name":"Discovery task 0","status":"Scan in process"},{"taskId":36457,"name":"Discovery task 1","status":"Scan FAILED"},{"taskId":36458,"name":"Discovery task 2","status":"Scan CANCELED by user"},{"taskId":36459,"name":"Discovery task 3","status":"Scan completed (Successful)"},{"taskId":36460,"name":"Discovery task 4","status":"Scan completed (Partial SUCCESSFUL)"},{"taskId":36461,"name":"Discovery task 5","status":"Scan completed (Processing Result)"},{"taskId":36462,"name":"Discovery task 6","status":null},{"taskId":36463,"name":"Discovery task 7","status":"Scan in process"},{"taskId":36464,"name":"Discovery task 8","status":"Scan FAILED"},{"taskId":36465,"name":"Discovery task 9","status":"Scan CANCELED by user"}]
+
+
+
+
+
+

Start MS AD scan task

+
+

Enables administrators to start a ms ad scan for a specific task

+
+
+

V2 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/ad_task/{taskId}/start
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task/31166/start' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3908' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3908'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V3

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/ad_task/{taskId}/start
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task/36860/start' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4197' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4197'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete MS AD scan task

+
+

V2 - Deprecated

+
+
+

Enables administrators to delete a specific ms ad scanning task.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v2/ad_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v2/ad_task/30964' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer3902' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst3902'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+

V3

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v3/ad_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v3/ad_task/36658' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4191' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4191'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Azure Key Vault Discovery Tasks

+
+

Add Azure Key Vault scan task

+
+

Enables administrators to create a scan task in search of SSL certificates.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

year

Number

Year

[]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

azureAccountId

Number

Azure account id

[Must be positive, Must not be null]

resourceGroup

String

Azure resource group name

[Must not be empty]

keyVault

String

Azure key vault name

[Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-3912' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"azureAccountId":51,"resourceGroup":"resourceGroup","keyVault":"keyVault","name":"AQXDQBODJZTNRDMNDBMOYYIVRVWBVHJW","certBucketId":"a6496c3f-9af0-4c9e-9265-19e0db14c2ad","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":1,"dayOfMonth":1,"dayOfWeek":3,"year":3044}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created task

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v1/azure_task/31368
+
+
+
+
+
+

Update Azure Key Vault scan task

+
+

Enables administrators to edit an Azure Key Vault scan task.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Task name

[Must not be empty, Size must be between 1 and 256 inclusive]

certBucketId

String

Id of the bucket to which this task will be applied

[Must not be null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

[Must not be empty]

timeZone

String

Time zone

[Must not be empty]

time

Object

Time

[Must not be null]

time.hours

Number

Hours

[]

time.minutes

Number

Minutes

[]

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

[Must be at least 1, Must be at most 12]

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

[Must be at least 1, Must be at most 31]

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

[Must be at least 1, Must be at most 7]

year

Number

Year

[]

azureAccountId

Number

Azure account id

[]

resourceGroup

String

Azure resource group name

[]

keyVault

String

Azure key vault name

[]

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/azure_task/{id}
ParameterDescription

id

ID of task whose details are being updated

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task/31370' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-3981' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"azureAccountId":74,"resourceGroup":"resourceGroup","keyVault":"keyVault","name":"BSBULLMWTHWSLDIYGIDTIDEHAEZFMVFB","certBucketId":"76299aa7-d271-4e4f-86d0-4c7c9f9518d3","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":0,"minutes":0},"month":1,"dayOfMonth":1,"dayOfWeek":3,"year":3044}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Get Azure Key Vault scan task

+
+

Enables the administrator to get the parameters of a particular task which he/she is authorized to view and manage.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/azure_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task/31369' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-3969' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Task name

status

String

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

frequency

String

Task frequency. Possible values are [Manual, Daily, Weekly, Monthly, Quarterly, SemiAnnually, Annually, Once]

timeZone

String

Time zone

time

Object

Time

time.hours

Number

Hours

time.minutes

Number

Minutes

month

Number

Month. Possible values is 1 for January, 2 for February and etc.

year

Number

Year

dayOfMonth

Number

Day of month. Possible values is 1 for 1st day of month, 2 for 2nd day of month and etc.

dayOfWeek

Number

Day of week. Possible values is 7 for Sunday, 1 for Monday, 2 for Tuesday and etc.

azureAccountId

Number

Azure account id

resourceGroup

String

Azure resource group name

keyVault

String

Azure key vault name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 230
+
+{"name":"Discovery task 0","frequency":"Daily","timeZone":"UTC+00:00 - GMT, UCT, UTC, WET, EGST","time":{"hours":9,"minutes":14},"status":"Scan in process","azureAccountId":70,"resourceGroup":"resourceGroup","keyVault":"keyVault"}
+
+
+
+
+
+

Get Azure Key Vault scan task list

+
+

Enables the administrator to get the list of existing tasks of scanning which he/she is authorized to view and manage.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Task name

status

Task status. Values: [IN_PROCESS, FAILED, CANCELED, SUCCESSFUL, PARTIAL_SUCCESSFUL, PROCESSING_RESULT, null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task?size=10&position=0' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-4050' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of network discovery tasks available according to the filtering applied

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Scan Tasks

[].taskId

Number

Scan Task ID

[].name

String

Name of Scan Task

[].status

String

Scan Task Status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 10
+Content-Type: application/json
+Content-Length: 743
+
+[{"taskId":31399,"name":"Discovery task 9","status":"Scan CANCELED by user"},{"taskId":31398,"name":"Discovery task 8","status":"Scan FAILED"},{"taskId":31397,"name":"Discovery task 7","status":"Scan in process"},{"taskId":31396,"name":"Discovery task 6","status":null},{"taskId":31395,"name":"Discovery task 5","status":"Scan completed (Processing Result)"},{"taskId":31394,"name":"Discovery task 4","status":"Scan completed (Partial SUCCESSFUL)"},{"taskId":31393,"name":"Discovery task 3","status":"Scan completed (Successful)"},{"taskId":31392,"name":"Discovery task 2","status":"Scan CANCELED by user"},{"taskId":31391,"name":"Discovery task 1","status":"Scan FAILED"},{"taskId":31390,"name":"Discovery task 0","status":"Scan in process"}]
+
+
+
+
+
+

Start Azure Key Vault scan task

+
+

Enables administrators to start an Azure Key Vault scan for a specific task

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/azure_task/{taskId}/start
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task/31402/start' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-4062' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete Azure Key Vault scan task

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/azure_task/{taskId}
ParameterDescription

taskId

Task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/azure_task/31401' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: nick-4056' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Discovery Assignment Rules

+
+

Discovery Assignment Rule Filters

+
+
Filter Structure
+
+

Each filter object in the filters array contains the following fields:

+
+
+
    +
  • +

    filters[].filterType: Specifies the type of filter as a string.

    +
  • +
  • +

    filters[].matchType: Defines the matching criteria for the filter.

    +
  • +
  • +

    filters[].value: Represents the value to be matched against, based on the matchType.

    +
  • +
+
+
+
+
Filter Types and Rules
+
+

The behavior of the filter depends on the filterType specified:

+
+
+
    +
  • +

    If filters[].filterType is any value from the list: COMMON_NAME, ORGANIZATION, ORGANIZATION_UNIT, CITY, STATE, COUNTRY, SUBJECT_ALT_NAME, ISSUER, IP, PORT, DOMAIN_COMPONENT, TEMPLATE_NAME, KU, EKU, HOSTNAME then filters[].matchType must correspond to a valid value from the list:

    +
    +
      +
    • +

      MATCHES: Checks if the value matches exactly.

      +
    • +
    • +

      STARTS_WITH: Checks if the value starts with a given substring.

      +
    • +
    • +

      ENDS_WITH: Checks if the value ends with a given substring.

      +
    • +
    • +

      CONTAINS: Checks if the value contains a given substring.

      +
    • +
    • +

      MATCH_REGEX: Checks if the value matches a given regular expression.

      +
    • +
    +
    +
  • +
+
+
+

filters[].value: Can be correct string representing the value that the filter should match according to the specified matchType.

+
+
+
    +
  • +

    If filters[].filterType is EXPIRATION:

    +
    +
      +
    • +

      filters[].matchType must be GREATER_THAN, which is the only allowed value in this context and corresponds to filters[].value which represents an integer value with specific meanings:

      +
    • +
    • +

      0: Used to filter for non-expired SSL certificates only.

      +
    • +
    • +

      1 to 365: Used to filter for non-expired certificates and include certificates that have expired no more than the specified number of days ago.

      +
    • +
    +
    +
  • +
+
+
+
+
Filter Examples
+
+
    +
  1. +

    Common filtering:

    +
    +
      +
    • +

      filters[].filterType: COMMON_NAME

      +
    • +
    • +

      filters[].matchType: MATCHES

      +
    • +
    • +

      filters[].value: example.com

      +
    • +
    +
    +
  2. +
+
+
+

This filter would match any records where the COMMON_NAME field matches the substring example.com.

+
+
+
    +
  1. +

    Filtering with Expiration:

    +
    +
      +
    • +

      filters[].filterType: EXPIRATION

      +
    • +
    • +

      filters[].matchType: GREATER_THAN

      +
    • +
    • +

      filters[].value: 30

      +
    • +
    +
    +
  2. +
+
+
+

This filter would include certificates that are still valid or have expired no more than 30 days ago.

+
+
+

Make sure to select the appropriate filterType, matchType, and value based on these rules to ensure the desired filtering behavior for assignment rules.

+
+
+
+
+

Create discovery assignment rule

+
+

Assignment Rules are associated with discovery tasks to assign 'Unmanaged' certificates (those not issued by SCM) to a particular Organization or Department

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Assignment rule name

[Must not be null, Size must be between 1 and 128 inclusive]

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

certType

String

Certificate type. Default value is SSL for backward compatibility. Values: [SSL, SMIME, CodeSign, Device]

[]

filters[]

Array

Array of rule filters

[Must not be empty]

filters[].filterType

String

Rule filter type

[]

filters[].matchType

String

Rule match type

[]

filters[].value

String

Rule value

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer4215' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst4215' \
+    -d '{"name":"WRFEHFFPZCGPVDIQYSSMNKJSFFCZTGUB","orgId":1854,"filters":[{"filterType":"ORGANIZATION","matchType":"MATCHES","value":"org4Test"}],"certType":"SSL"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created assignment rule

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v1/assignmentrule/271
+
+
+
+
+
+

Update discovery assignment rule

+
+

Enables the administrator to edit the existing assignment rule.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

ruleId

Number

Assignment rule ID

[Must be at least 1]

name

String

Assignment rule name

[Must not be null, Size must be between 1 and 128 inclusive]

certType

String

Certificate type. Default value is SSL for backward compatibility. Values: [SSL, SMIME, CodeSign, Device]

[]

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

filters[]

Array

Array of rule filters

[Must not be empty]

filters[].filterType

String

Rule filter type

[]

filters[].matchType

String

Rule match type

[]

filters[].value

String

Rule value

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer9961' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst9961' \
+    -d '{"ruleId":5726,"name":"ESTMBSFXDTMMPDYFRMVMITYMZJBKQEZX","orgId":1884,"filters":[{"filterType":"ORGANIZATION","matchType":"STARTS_WITH","value":"org4Test"}],"certType":"SSL"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Find discovery assignment rule by ID

+
+

Enables the administrator to find the assignment rule by its ID.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/assignmentrule/{ruleId}
ParameterDescription

ruleId

Assignment rule ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule/5120' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer9343' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst9343'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Assignment rule name

orgId

Number

Assignment rule organization ID

certType

String

Assignment rule certificate type

filters[]

Array

Array of rule filters

filters[].filterType

String

Rule filter type

filters[].matchType

String

Rule match type

filters[].value

String

Rule value

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 118
+
+{"name":"Assignment rule 9346 [organization: org4Test, customer ID: 1161]","orgId":1880,"filters":[],"certType":"SSL"}
+
+
+
+
+
+

Get discovery assignment rules count

+
+

Enables administrators to get the number of existing assignment rules for the organization or department delegated to them.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule/count' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer8725' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst8725'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

count

Number

Assignment rules count

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 13
+
+{"count":202}
+
+
+
+
+
+

Get discovery assignment rules ID list

+
+

Enables Admins to get the list of existing assignment rules IDs for the organization or department delegated to them.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule/?size=10&position=0' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer16756' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst16756'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of assignment rule IDs

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 61
+
+[12392,12393,12394,12395,12396,12397,12398,12399,12400,12401]
+
+
+
+
+
+

Delete discovery assignment rule

+
+

Enables the administrator to delete a particular assignment rule that is applicable to the organization or department delegated to them.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/assignmentrule/{ruleId}
ParameterDescription

ruleId

Assignment rule ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/assignmentrule/12594' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer16961' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst16961' \
+    -d '{"ruleId":0,"name":"PHMASTGXYUECSINCSNMIEEWHGDTDFRAL","orgId":1906,"filters":[{"filterType":"ORGANIZATION","matchType":"STARTS_WITH","value":"org4Test"}],"certType":"SSL"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Discovery Certificate Buckets

+
+

Create discovery certificate bucket

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Cert Bucket name

[Must not be null, Size must be between 1 and 128 inclusive]

assignmentRules

Array

Assignment rule IDs

[]

orgDelegations

Array

Delegated organization IDs

[]

authenticationEnabled

Boolean

Is REST Authentication enabled

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer3381' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name": "Cert Bucket Example", "assignmentRules": [62], "orgDelegations":[1517] , "authenticationEnabled": true}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created cert bucket

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/discovery/v1/bucket/4afc6d05-1206-4d05-b28b-3842da11199f
+Content-Type: application/json
+Content-Length: 105
+
+{"clientId":"66bd6a7e-b80d-42e1-9afb-897cea95741b","clientSecret":"96016664-d59a-4dcf-b6e8-8e7ca1997e3c"}
+
+
+
+
+
+

Update discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{bucketId}
ParameterDescription

bucketId

Cert Bucket ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Cert Bucket name

[Must not be null, Size must be between 1 and 128 inclusive]

assignmentRules

Array

Assignment rule IDs

[]

authenticationEnabled

Boolean

Is REST Authentication enabled

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/a609da73-f632-4290-8373-711edf37384f' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer3413' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name": "Cert Bucket Example", "assignmentRules": [66],  "authenticationEnabled": true}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

String

Cert Bucket ID

name

String

Cert Bucket name

assignmentRules

Array

Assignment rule IDs

orgDelegations

Array

Delegated organization IDs

authenticationEnabled

Boolean

Is REST Authentication enabled

clientId

String

REST Authentication Client id. It will be shown all the time if authentication on a bucket is enabled, and will not be shown if authentication is disabled.

clientSecret

String

REST Authentication Client secret. It will be shown only once if you decide to enable authentication on the bucket, if it was disabled before.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 254
+
+{"clientId":"89cd2a34-fde4-46db-9ba4-0f984ce6dd37","clientSecret":"d3f0ec26-6c26-4517-b791-896cc3aed8ec","id":"a609da73-f632-4290-8373-711edf37384f","name":"Cert Bucket Example","authenticationEnabled":true,"assignmentRules":[66],"orgDelegations":[1533]}
+
+
+
+
+
+

Reset discovery certificate buckets client secret

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{bucketId}/reset-client-secret
ParameterDescription

bucketId

Cert Bucket ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/943eb30b-e4a9-496b-a8bc-bd2dda147839/reset-client-secret' -i -X PUT \
+    -H 'login: admin_customer3409' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

clientId

String

REST Authentication Client id.

clientSecret

String

REST Authentication Client secret.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 105
+
+{"clientId":"f1be6bbe-0d83-4e84-8cc6-3d9418084f27","clientSecret":"49e93901-6086-4b16-a1b7-eedfccd02bc0"}
+
+
+
+
+
+

Delegate organizations to existing discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{bucketId}/delegations
ParameterDescription

bucketId

Cert Bucket ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

delegationMode

String

Allowed values: [GLOBAL_FOR_CUSTOMER, CUSTOMIZED]

[Must not be null]

orgDelegations

Array

Delegated organization IDs. Should be absent for GLOBAL_FOR_CUSTOMER delegation mode

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/eba2ba43-3379-40b6-a486-beae4437b84a/delegations' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer3387' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"delegationMode": "CUSTOMIZED", "orgDelegations": [1520]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

String

Cert Bucket ID

name

String

Cert Bucket name

assignmentRules

Array

Assignment rule IDs

orgDelegations

Array

Delegated organization IDs

authenticationEnabled

Boolean

Is REST Authentication enabled

clientId

String

REST Authentication Client id

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 190
+
+{"clientId":"49094919-1898-4311-b245-9f46d7d5402f","id":"eba2ba43-3379-40b6-a486-beae4437b84a","name":"test bucket","authenticationEnabled":true,"assignmentRules":[],"orgDelegations":[1520]}
+
+
+
+
+
+

Find discovery certificate bucket by ID

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{id}
ParameterDescription

id

Cert Bucket ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/ba5efdf3-777a-4a6c-a395-c8c7a38f1bcc' -i -X GET \
+    -H 'login: admin_customer3397' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

String

Cert Bucket ID

name

String

Cert Bucket name

assignmentRules

Array

Assignment rule IDs

orgDelegations

Array

Delegated organization IDs

authenticationEnabled

Boolean

Is REST Authentication enabled

clientId

String

REST Authentication Client id. It will be shown all the time if authentication on a bucket is enabled, and will not be shown if authentication is disabled.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 200
+
+{"clientId":"e0a31298-2c5c-4fc1-b205-0c371590f740","id":"ba5efdf3-777a-4a6c-a395-c8c7a38f1bcc","name":"Example Cert Bucket","authenticationEnabled":true,"assignmentRules":[64],"orgDelegations":[1525]}
+
+
+
+
+
+

List discovery certificate buckets

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

name

Cert Bucket name

orgId

Organization ID

delegationMode

Delegation mode. Possible values: 'GLOBAL_FOR_CUSTOMER' and’CUSTOMIZED'

position

the first position (entry) to return from the results of the query

size

Count of entries

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket?name=test&orgId=1527&delegationMode=CUSTOMIZED&position=0&size=10' -i -X GET \
+    -H 'login: admin_customer3401' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Certificate buckets list

[].id

String

ID

[].name

String

Name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 68
+
+[{"id":"ada63b63-6629-4900-a443-b48b1350b2a0","name":"test bucket"}]
+
+
+
+
+
+

Delete discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{id}
ParameterDescription

id

Cert Bucket ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/8404460c-fa57-43bb-8023-729a7d308515' -i -X DELETE \
+    -H 'login: admin_customer3390' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Certificates in discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{id}/certificates
ParameterDescription

id

Cert Bucket ID

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/6c657236-bdc6-4da8-9694-0e708e4302d2/certificates?position=0&size=0' -i -X GET \
+    -H 'login: admin_customer3393' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

total

Number

Total count of founded certificates

data.[]

Array

List of Certificates

data.[0].hash

String

Certificate hash

data.[0].details

Object

Certificate details

data.[0].details.cn

String

Certificate common name

data.[0].details.validFrom

String

Certificate issue date

data.[0].details.validTo

String

Certificate expiry date

data.[0].details.subject

Object

Certificate subject

data.[0].details.san

Array

Certificate subject alternative names

data.[0].details.keyAlgorithm

String

Certificate key algorithm

data.[0].details.keySize

Number

Certificate key size

data.[0].details.signatureAlgorithm

String

Certificate signature algorithm

data.[0].details.sn

String

Certificate serial number

data.[0].details.md5Hash

String

Certificate md5 hash

data.[0].details.sha1Hash

String

Certificate sha1 hash

data.[0].details.ku

Array

Certificate key usage

data.[0].details.eku

Array

Certificate extended key usage

data.[0].details.issuer

Object

Certificate issuer

data.[0].details.precert

Boolean

Precert certificate indicator

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 494
+
+{"total":1,"data":[{"hash":"11a736dd5d67af1ed5b6a14fbf92ca8fe97df841","details":{"cn":"*.ssl.hwcdn.net","validFrom":"2025-08-15T09:12:40Z","validTo":"2025-08-15T09:12:40Z","issuer":{},"subject":{},"san":[],"keyAlgorithm":"RSA","keySize":2048,"signatureAlgorithm":"SHA256withRSA","sn":"32616335373265322D343361362D336331332D396537632D643330306338303130643332","md5Hash":"0e6d4f8af5d5a163676d0780b3b4b54e","sha1Hash":"11a736dd5d67af1ed5b6a14fbf92ca8fe97df841","ku":[],"eku":[],"precert":false}}]}
+
+
+
+
+
+

Run rules against discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{id}/runrules
ParameterDescription

id

Cert Bucket ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/92cc880d-7895-4002-9fbe-a0e9f25ddb60/runrules' -i -X POST \
+    -H 'login: admin_customer3373' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Assign certificates in discovery certificate bucket

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/discovery/v1/bucket/{id}/assign
ParameterDescription

id

Cert Bucket ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

hashes

Array

List of certificate hashes

[Must not be empty]

certType

String

Certificate type. Values: [SSL, SMIME, CodeSign, Device]

[Must not be null]

organizationId

Number

Organization ID

[Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/bucket/9880279b-020c-4c3c-9b73-542aa2068e52/assign' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer3377' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"hashes":["hash"],"certType":"SSL","organizationId":12}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+

Discovery Operations

+
+

Get discovery operations list

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/discovery/v1/{taskType}/{taskId}/operation
ParameterDescription

taskType

Discovery task type. Allowed values: [ad_task, net_task, azure_task]

taskId

Discovery task ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/net_task/31404/operation' -i -X GET \
+    -H 'Accept: application/json' \
+    -H 'login: nick-4070' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

total

Number

Operations count. Deprecated, X-Total-Count header should be used instead

data

Array

List of operations

data[].id

String

Operation ID

data[].status

String

Operation status

data[].created

String

Operation create date (start scan)

data[].modified

String

Operation last modification date

data[].bucketId

String

ID of the respective certificate bucket

data[].error

String

Error description and details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 0
+Content-Type: application/json
+Content-Length: 684
+
+{"total":4,"data":[{"id":"2c9780878596231201859c0992dc0004","status":"failed","created":"2023-01-10T14:15:51.260Z","modified":"2023-01-10T14:15:51.358Z","bucketId":"123","error":"Internal error"},{"id":"2c9780878596231201859d39f42d0005","status":"failed","created":"2023-01-10T19:48:19.117Z","modified":"2023-01-10T19:48:19.216Z","bucketId":"123","error":"Internal error"},{"id":"2c978087859623120185a07545370006","status":"completed","created":"2023-01-11T10:51:58.135Z","modified":"2023-01-11T10:51:58.232Z","bucketId":"123"},{"id":"2c978087859623120185a0861ad20007","status":"completed","created":"2023-01-11T11:10:21.394Z","modified":"2023-01-11T11:10:21.491Z","bucketId":"123"}]}
+
+
+
+
+
+

Stop discovery operation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + + + + + +
Table 1. /api/discovery/v1/{taskType}/{taskId}/operation/{operationId}/stop
ParameterDescription

taskType

Discovery task type. Allowed values: [ad_task, net_task, azure_task]

taskId

Discovery task ID

operationId

Operation ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/net_task/31405/operation/2c978087859623120185a07545370106/stop' -i -X POST \
+    -H 'login: nick-4075' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Get result of discovery operation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + + + + + +
Table 1. /api/discovery/v1/{type}/{taskId}/operation/{opId}/result
ParameterDescription

type

Discovery task type. Allowed values: [ad_task, net_task, azure_task]

taskId

Discovery task ID

opId

Operation ID

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/discovery/v1/net_task/31403/operation/2c9b8087864fefb701865a26f77b0001/result' -i -X GET \
+    -H 'Accept: application/json' \
+    -H 'login: nick-4065' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

total

Number

Total count of founded certificates. Deprecated, X-Total-Count header should be used instead

data.[]

Array

Array of founded certificates

data.[0].operation

Object

Operation details

data.[0].operation.id

String

Operation ID

data.[0].operation.created

String

Operation create date

data.[0].status

Object

Certificate status

data.[0].status.tlsVersion

Number

Certificate status: tls version

data.[0].status.handshakeMs

Number

Certificate status: handshake MS

data.[0].status.cipherSuite

String

Certificate status: ciper suite

data.[0].status.nameLookupMs

Number

Certificate status: name lookup

data.[0].created

String

Certificate create date

data.[0].certificate

Object

Certificate data

data.[0].certificate.hash

String

Certificate hash

data.[0].certificate.metadata.managedId

String

Certificate managed id

data.[0].certificate.metadata.hidden

Boolean

Is certificate hidden

data.[0].certificate.metadata.discoveryTime

String

Date when certificate was discovered

data.[0].certificate.details

Object

Certificate details

data.[0].certificate.details.cn

String

Certificate common name

data.[0].certificate.details.validFrom

String

Certificate issue date

data.[0].certificate.details.validTo

String

Certificate expiry date

data.[0].certificate.details.subject

Object

Certificate subject

data.[0].certificate.details.san

Array

Certificate subject alternative names

data.[0].certificate.details.keyAlgorithm

String

Certificate key algorithm

data.[0].certificate.details.keySize

Number

Certificate key size

data.[0].certificate.details.signatureAlgorithm

String

Certificate signature algorithm

data.[0].certificate.details.sn

String

Certificate serial number

data.[0].certificate.details.md5Hash

String

Certificate md5 hash

data.[0].certificate.details.sha1Hash

String

Certificate sha1 hash

data.[0].certificate.details.issuer

Object

Certificate issuer

data.[0].certificate.details.ku

Array

Certificate key usage

data.[0].certificate.details.eku

Array

Certificate key usage

data.[0].certificate.details.precert

Boolean

Precert certificate

data.[0].location

Object

Certificate location

data.[0].location.type

String

Certificate location type

data.[0].location.details

Object

Certificate location details

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 1282
+
+{"total":1,"data":[{"certificate":{"hash":"09a736dd5d67af1ed5b6a14fbf92ca8fe97df839","metadata":{"managedId":"ssl:130","hidden":false,"discoveryTime":"2024-06-20T11:27:13.657Z"},"details":{"cn":"*.ssl.hwcdn.net","validFrom":"2022-12-30T00:00:00Z","validTo":"2024-01-19T23:59:59Z","issuer":{},"subject":{},"san":[],"keyAlgorithm":"RSA","keySize":2048,"signatureAlgorithm":"SHA256withRSA","sn":"2AC572E243A63C139E7CD300C8010D32","md5Hash":"0e6d4f8af5d5a163676d0780b3b4b54e","sha1Hash":"09a736dd5d67af1ed5b6a14fbf92ca8fe97df839","ku":[],"eku":[],"precert":false}},"location":{"type":"NETWORK_HOST","details":{"ip":"151.139.128.14","port":443,"address":"sectigo.com","name":null,"dn":null,"upn":null,"objectType":null,"requestId":null,"haGroupId":null,"template":null,"dateCreated":null,"type":null,"requesterEmail":null,"backend":null,"host":null,"requesterName":null,"site":null,"hostName":null,"id":null,"exportable":null,"reusable":null,"uri":null,"arn":null,"exported":null,"inUse":null,"inUseBy":null,"scope":null,"labels":null}},"status":{"tlsVersion":1,"cipherSuite":"123","handshakeMs":2,"nameLookupMs":3,"status":null,"additionalEmails":null},"operation":{"id":"2c9b8087864fefb701865a26f77b0001","created":"2023-02-16T12:15:48.604401Z"},"created":"2023-01-26T05:42:45.212Z"}]}
+
+
+
+
+
+
+
+
+

Notifications

+
+
+

View notifications

+
+

List notifications

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

id

Notification ID

description

Notification description

orgId

Notification organization ID

selectedOrgType

Selected organization type. Values: [ANY, ANYDEPT, SELECTED]

type

Notification type. Values: [ClientCertExpiration, ClientCertRevoked, SSLApproved, SSLAwaitingApproval, SSLDeclined, SSLExpiration, SSLIssuanceFailed, SSLRevoked, DiscoveryScanSummary, SSLSAApprovedToRA, AdminCreation, DomainAwaitingApproval, DomainApproved, SSLEnrolled, CSCertInvitation, CSCertIssued, CSCertDownloaded, CSCertRevoked, CSCertExpiration, CSCertRequested, EmailValidation, EmailInvitation, DCVExpiration, DCVValidated, DCVNeeded, ExSSLCertificateInstalled, ExSSLInstallationFailed, IdPLoginEmailInvitation, CsRequestDeclined, CsRequestSigned, DeveloperCreated, DeveloperResetPassword, DeveloperNewEmail, CsRequestCreated, CsCsfRevoke, DeviceExpiration, DeviceRevoked, DeviceAwaitingApproval, ArFailed, ManualInstallReady, DeviceEnrolled, DeviceApproved, DeviceDeclined, AdminChangePasswordByApi, SSLBulkAwaitingApproval, SSLBulkEnrollCompleted, SSLEnrolledDl, SMIMEEnrolledDl, DeviceEnrolledDl, CsEnrolledDl, MsAgentChangeStatus, NetworkAgentDisconnected, WebFormLogin, WebFormInvitation, DomainAwaitingApprovalMrao, ReportGenerated, DcvAutoRenewFailed, SasLoginEmailInvitation, DnsConnectorDisconnected, CAConnectorDisconnected, PrivateCaExpiration, SubscriptionChange, CertificateUsageThreshold, CertificateUsageExceedsInventory]

certTypeId

Notification profile ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/notification/v1?id=60&description=ssl-revoke&orgId=2783&selectedOrgType=ANYDEPT&type=SSLRevoked&certTypeId=1935' -i -X GET \
+    -H 'login: admin_customer20431' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of notifications.

[].id

Number

Notification ID

[].description

String

Notification description

[].type

String

Notification type

[].created

String

Created date

[].createdBy

String

Name of the administrator who created the notification.

[].modified

String

Modified date

[].modifiedBy

String

Name of the administrator who last modified the notification.

[].orgData

Object

Data for organization configuration

[].orgData.selectedOrgType

String

Type of organization selection.

[].orgData.orgDelegations

Array

Selected organizations ID

[].recipientData

Object

Data for recipients configuration

[].recipientData.notifyRoles

Array

Notify roles.

[].recipientData.recipients.[]

Array

Recipients to notify

[].recipientData.recipients.[].type

String

Type of recipient

[].recipientData.recipients.[].value

String

Value of recipient

[].additionalData

Object

Additional data for notification configuration

[].additionalData.days

Number

Number of remaining days

[].additionalData.certTypeId

Number

Profile id that this notification belongs to

[].additionalData.freq

String

Notification frequency

[].additionalData.revokedByAdmin

Boolean

For certificates, revoked by admin

[].additionalData.revokedByUser

Boolean

For certificates, revoked by user

[].type

String

Notification type

[].id

Number

Notification ID

[].description

String

Notification description

[].active

Boolean

For certificates, revoked by user

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 531
+
+[{"description":"ssl-revoke","active":true,"orgData":{"selectedOrgType":"ANYDEPT","orgDelegations":[2783]},"recipientData":{"notifyRoles":["MRAO","APPROVER"],"recipients":[{"type":"EMAIL","value":"test@sectigo.com"}]},"additionalData":{"days":0,"certTypeId":1935,"freq":"ONCE","revokedByAdmin":true,"revokedByUser":false},"type":"SSLRevoked","id":60,"created":"2025-08-15T09:20:33.828Z","createdBy":"client-admin-20432 client-admin-20432","modified":"2025-08-15T09:20:33.828Z","modifiedBy":"client-admin-20432 client-admin-20432"}]
+
+
+
+
+
+

Available notification types

+
+

Get the notification types that are available for the current administrator.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/notification/v1/types' -i -X GET \
+    -H 'login: admin_customer20428' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Notification types

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 531
+
+["ClientCertExpiration","ClientCertRevoked","SMIMEEnrolledDl","CSCertDownloaded","CSCertRevoked","CSCertExpiration","CSCertRequested","CsEnrolledDl","SSLApproved","SSLAwaitingApproval","SSLDeclined","SSLExpiration","SSLIssuanceFailed","SSLRevoked","DiscoveryScanSummary","ExSSLCertificateInstalled","ExSSLInstallationFailed","ArFailed","ManualInstallReady","SSLEnrolledDl","AdminCreation","DomainAwaitingApproval","DomainAwaitingApprovalMrao","DomainApproved","MsAgentChangeStatus","NetworkAgentDisconnected","PrivateCaExpiration"]
+
+
+
+
+
+
+

Manage notifications

+
+

Create notification

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

description

String

Notification description

[Size must be between 3 and 256 inclusive]

type

String

Notification type

[Must not be null]

orgData

Object

Delegated organization details

[]

orgData.selectedOrgType

String

Organization selection type. Values: [ANY, ANYDEPT, SELECTED]

[]

orgData.orgDelegations

Array

Selected organization ID’s

[]

recipientData

Object

Notification recipient details

[Must not be null]

recipientData.notifyRoles

Array

Notify roles list

[]

recipientData.recipients

Array

Notification recipients

[]

recipientData.recipients.[].type

String

Notification recipient type

[Must not be null]

recipientData.recipients.[].value

String

Notification recipient value

[]

additionalData

Object

Notification additional details

[]

additionalData.revokedByAdmin

Boolean

For certificates, revoked by admin

[]

additionalData.revokedByUser

Boolean

For certificates, revoked by user

[]

additionalData.certTypeId

Number

Profile id that this notification belongs to

[]

additionalData.days

Number

Number of remaining days

[]

additionalData.freq

String

Notification frequency. Values: [ONCE, DAILY]

[]

active

Boolean

Status indicating whether the notification is active or not. Default value is true

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/notification/v1' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20416' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"description":"ssl-revoke","active":true,"orgData":{"selectedOrgType":"SELECTED","orgDelegations":[2773]},"recipientData":{"notifyRoles":["REQUESTER","SSL_RAO","MRAO"],"recipients":[{"type":"EMAIL","value":"aaa@sectigo.com"}]},"additionalData":{"days":0,"certTypeId":1930,"freq":"ONCE","revokedByAdmin":false,"revokedByUser":true},"type":"SSLRevoked"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created notification

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/notification/v1/57
+
+
+
+
+
+

Update notification

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/notification/v1/{id}
ParameterDescription

id

Notification ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

description

String

Notification description

[Size must be between 3 and 256 inclusive]

orgData

Object

Delegated organization details

[]

orgData.selectedOrgType

String

Organization selection type. Values: [ANY, ANYDEPT, SELECTED]

[]

orgData.orgDelegations

Array

Selected organization ID’s

[]

recipientData

Object

Notification recipient details

[Must not be null]

recipientData.notifyRoles

Array

Notify roles list

[]

recipientData.recipients

Array

Notification recipients

[]

recipientData.recipients.[].type

String

Notification recipient type

[Must not be null]

recipientData.recipients.[].value

String

Notification recipient value

[]

additionalData

Object

Notification additional details

[]

additionalData.revokedByAdmin

Boolean

For certificates, revoked by admin

[]

additionalData.revokedByUser

Boolean

For certificates, revoked by user

[]

additionalData.certTypeId

Number

Profile id that this notification belongs to

[]

additionalData.days

Number

Number of remaining days

[]

additionalData.freq

String

Notification frequency. Values: [ONCE, DAILY]

[]

active

Boolean

Status indicating whether the notification is active or not. Default value is true

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/notification/v1/62' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20434' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"description":"ssl-revoke","active":true,"orgData":{"selectedOrgType":"SELECTED","orgDelegations":[2785]},"recipientData":{"notifyRoles":["REQUESTER","SSL_RAO","MRAO"],"recipients":[{"type":"EMAIL","value":"aaa@sectigo.com"}]},"additionalData":{"days":0,"certTypeId":1936,"freq":"ONCE","revokedByAdmin":false,"revokedByUser":true}}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 502
+
+{"description":"ssl-revoke","active":true,"orgData":{"selectedOrgType":"SELECTED","orgDelegations":[2785]},"recipientData":{"notifyRoles":["MRAO","REQUESTER","SSL_RAO"],"recipients":[{"type":"EMAIL","value":"aaa@sectigo.com"}]},"additionalData":{"days":0,"certTypeId":1936,"freq":"ONCE","revokedByAdmin":false,"revokedByUser":true},"type":"SSLRevoked","id":62,"created":"2025-08-15T09:20:34.039Z","createdBy":"client-admin-20435 client-admin-20435","modifiedBy":"client-admin-20435 client-admin-20435"}
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Notification ID

description

String

Notification description

type

String

Notification type

created

String

Created date

createdBy

String

Name of the administrator who created the notification.

modified

String

Modified date

modifiedBy

String

Name of the administrator who last modified the notification.

orgData

Object

Data for organization configuration

orgData.selectedOrgType

String

Type of organization selection.

orgData.orgDelegations

Array

Selected organizations ID

recipientData

Object

Data for recipients configuration

recipientData.notifyRoles

Array

Notify roles.

recipientData.recipients.[]

Array

Recipients to notify

recipientData.recipients.[].type

String

Type of recipient

recipientData.recipients.[].value

String

Value of recipient

additionalData

Object

Additional data for notification configuration

additionalData.days

Number

Number of remaining days

additionalData.freq

String

Notification frequency.

active

Boolean

Status indicating whether the notification is active or not

additionalData.certTypeId

Number

Profile id that this notification belongs to

additionalData.freq

String

Notification frequency

additionalData.revokedByAdmin

Boolean

For certificates, revoked by admin

additionalData.revokedByUser

Boolean

For certificates, revoked by user

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 502
+
+{"description":"ssl-revoke","active":true,"orgData":{"selectedOrgType":"SELECTED","orgDelegations":[2785]},"recipientData":{"notifyRoles":["MRAO","REQUESTER","SSL_RAO"],"recipients":[{"type":"EMAIL","value":"aaa@sectigo.com"}]},"additionalData":{"days":0,"certTypeId":1936,"freq":"ONCE","revokedByAdmin":false,"revokedByUser":true},"type":"SSLRevoked","id":62,"created":"2025-08-15T09:20:34.039Z","createdBy":"client-admin-20435 client-admin-20435","modifiedBy":"client-admin-20435 client-admin-20435"}
+
+
+
+
+
+

Delete notification

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/notification/v1/{id}
ParameterDescription

id

Notification ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/notification/v1/58' -i -X DELETE \
+    -H 'login: admin_customer20422' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+
+
+

Administrators

+
+
+

View administrators

+
+

List administrators

+
+

List administrators according to the specified filter. +Note: "IdP Template" administrators are not supported by current method and are filtered out. +In order to receive a list of IdP templates, please use "List IdP Templates" method from "Template Administrators" section.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

type

Admin type filter. Allowed values: STANDARD, IDP, SAS, API, DYNAMIC_IDP_TEMPLATE

login

Filter by login

email

Filter by E-mail

activeState

Filter by Active State Allowed values: ACTIVE, SUSPENDED

orgId

Filter by Organization ID

templateId

Filter by assigned IdP template ID

identityProviderId

Filter by Identity Provider ID

role

Filter by role. Allowed values: MRAO, RAO_SSL, RAO_SMIME, RAO_CS, RAO_DEVICE, DRAO_SSL, DRAO_SMIME, DRAO_CS, DRAO_DEVICE

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1?size=10&position=0' -i -X GET \
+    -H 'login: admin_customer2114' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2114'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested admins

[].id

Number

Admin ID

[].type

String

Admin type

[].login

String

Admin login

[].email

String

Admin E-mail

[].forename

String

Admin forename

[].surname

String

Admin surname

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 3
+Content-Type: application/json
+Content-Length: 478
+
+[{"id":943,"type":"STANDARD","login":"testadmin_customer2114","forename":"client-admin-2119","surname":"client-admin-2119","email":"TestAdmin_Customer2114@aa.com"},{"id":942,"type":"STANDARD","login":"admindrao_customer2114","forename":"client-admin-2117","surname":"client-admin-2117","email":"2118aa@nobody.sectigo.com"},{"id":941,"type":"STANDARD","login":"admin_customer2114","forename":"client-admin-2115","surname":"client-admin-2115","email":"Admin_Customer2114@aa.com"}]
+
+
+
+
+
+

Get administrator details

+
+

Get detailed information about administrator.

+
+
+
+

Get standard administrator details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/896' -i -X GET \
+    -H 'login: admin_customer2006' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2006' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Admin identifier

type

String

Admin account type

forename

String

Forename

surname

String

Surname

email

String

Email

clientAdminCreator

Number

Identifier of creator Admin

login

String

Login

reseted

String

Password reset date (if password has been reset).

lastPasswordChange

String

Last password change date

passwordState

String

Admin’s password state. Possible values: 'ALIVE', 'EXPIRED' and 'NEVER_EXPIRE'

passwordExpiryDate

String

Password expiration date

authCert

String

Authentication Certificate Serial Number

identityProviderId

Number

Identifier of assigned Identity Provider

idp

String

Name of assigned Identity Provider

idpPersonId

String

Person Identifier (EPPN) in scope of Identity Provider

created

String

Admin creation date

modified

String

Admin last modification date

deleted

String

For deleted admins - the date when admin was deleted

title

String

Title or position

relationship

String

Administrator’s relationship to the company

phone

String

Telephone number

city

String

City / locality name

state

String

State or province name

country

String

Country

zip

String

Postal code

locale

String

Admin’s locale

status

String

Admin status. Deprecated. Value is always 'ACTIVE' for backward compatibility

activeState

String

Deprecated, see 'activeStatus' instead.

activeStatus

String

Active Status, possible values: ACTIVE and SUSPENDED

credentials[]

Array

Array of admin’s roles

credentials[].role

String

Admin’s role

credentials[].orgId

Number

Organization / Department ID

privileges

Array

Array of admin’s privileges

failedAttempts

Number

Number of failed attempts to log in

failedDate

String

Date of last failed attempt to log in

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 566
+
+{"id":896,"type":"STANDARD","status":"Active","forename":"client-admin-2013","surname":"client-admin-2013","login":"drao","email":"2014aa@nobody.sectigo.com","phone":"+123456789","created":"2025-08-15","modified":"2025-08-15","lastPasswordChange":"2025-08-15","credentials":[{"role":"DRAO_SSL","orgId":1131}],"passwordState":"ALIVE","passwordExpiryDate":"2025-11-15","authCert":"123456789AB","activeState":"Active","privileges":["allowManageDomains"],"failedAttempts":0,"identityProviderId":77,"idp":"Test Idp","idpPersonId":"admin.epp@test","activeStatus":"ACTIVE"}
+
+
+
+
+
+

Get API administrator details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/902' -i -X GET \
+    -H 'login: admin_customer2019' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2019' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Admin identifier

type

String

Admin account type

forename

String

Forename

surname

String

Surname

email

String

Email

clientAdminCreator

Number

Identifier of creator Admin

login

String

Login

reseted

String

Password reset date (if password has been reset).

lastPasswordChange

String

Last password change date

passwordState

String

Admin’s password state. Possible values: 'ALIVE', 'EXPIRED' and 'NEVER_EXPIRE'

passwordExpiryDate

String

Password expiration date

authCert

String

Authentication Certificate Serial Number

created

String

Admin creation date

modified

String

Admin last modification date

deleted

String

For deleted admins - the date when admin was deleted

title

String

Title or position

relationship

String

Administrator’s relationship to the company

phone

String

Telephone number

city

String

City / locality name

state

String

State or province name

country

String

Country

zip

String

Postal code

locale

String

Admin’s locale

status

String

Admin status. Deprecated. Value is always 'ACTIVE' for backward compatibility

activeState

String

Deprecated, see 'activeStatus' instead.

activeStatus

String

Active Status, possible values: ACTIVE and SUSPENDED

credentials[]

Array

Array of admin’s roles

credentials[].role

String

Admin’s role

credentials[].orgId

Number

Organization / Department ID

privileges

Array

Array of admin’s privileges

failedAttempts

Number

Number of failed attempts to log in

failedDate

String

Date of last failed attempt to log in

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 489
+
+{"id":902,"type":"API","status":"Active","forename":"client-admin-2026","surname":"client-admin-2026","login":"drao","email":"2027aa@nobody.sectigo.com","phone":"+123456789","created":"2025-08-15","modified":"2025-08-15","lastPasswordChange":"2025-08-15","credentials":[{"role":"DRAO_SSL","orgId":1134}],"passwordState":"ALIVE","passwordExpiryDate":"2025-11-15","authCert":"123456789AB","activeState":"Active","privileges":["allowManageDomains"],"failedAttempts":0,"activeStatus":"ACTIVE"}
+
+
+
+
+
+

Get IDP administrator details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/908' -i -X GET \
+    -H 'login: admin_customer2032' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2032' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Admin identifier

type

String

Admin account type

forename

String

Forename

surname

String

Surname

email

String

Email

clientAdminCreator

Number

Identifier of creator Admin

identityProviderId

Number

Identifier of assigned Identity Provider

idp

String

Name of assigned Identity Provider

idpPersonId

String

Person Identifier (EPPN) in scope of Identity Provider

idpLoginInvited

String

The date when login invitation was sent to the admin’s email.

templateId

Number

For IdP admins created automatically by IdP template - identifier of the parent Idp template.

created

String

Admin creation date

modified

String

Admin last modification date

deleted

String

For deleted admins - the date when admin was deleted

title

String

Title or position

relationship

String

Administrator’s relationship to the company

phone

String

Telephone number

city

String

City / locality name

state

String

State or province name

country

String

Country

zip

String

Postal code

locale

String

Admin’s locale

status

String

Admin status. Deprecated. Value is always 'ACTIVE' for backward compatibility

activeState

String

Deprecated, see 'activeStatus' instead.

activeStatus

String

Active Status, possible values: ACTIVE and SUSPENDED

credentials[]

Array

Array of admin’s roles

credentials[].role

String

Admin’s role

credentials[].orgId

Number

Organization / Department ID

privileges

Array

Array of admin’s privileges

failedAttempts

Number

Number of failed attempts to log in

failedDate

String

Date of last failed attempt to log in

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 441
+
+{"id":908,"type":"IDP","status":"Active","forename":"client-admin-2039","surname":"client-admin-2039","email":"2040aa@nobody.sectigo.com","phone":"+123456789","created":"2025-08-15","modified":"2025-08-15","credentials":[{"role":"DRAO_SSL","orgId":1137}],"activeState":"Active","privileges":["allowManageDomains"],"failedAttempts":0,"identityProviderId":79,"idp":"Test Idp","idpPersonId":"eppn-2039@nobody.ccmqa.com","activeStatus":"ACTIVE"}
+
+
+
+
+
+

Get SAS administrator details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/912' -i -X GET \
+    -H 'login: admin_customer2041' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2041' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Admin identifier

type

String

Admin account type

forename

String

Forename

surname

String

Surname

email

String

Email

clientAdminCreator

Number

Identifier of creator Admin

created

String

Admin creation date

modified

String

Admin last modification date

deleted

String

For deleted admins - the date when admin was deleted

title

String

Title or position

relationship

String

Administrator’s relationship to the company

phone

String

Telephone number

city

String

City / locality name

state

String

State or province name

country

String

Country

zip

String

Postal code

locale

String

Admin’s locale

status

String

Admin status. Deprecated. Value is always 'ACTIVE' for backward compatibility

activeState

String

Deprecated, see 'activeStatus' instead.

activeStatus

String

Active Status, possible values: ACTIVE and SUSPENDED

credentials[]

Array

Array of admin’s roles

credentials[].role

String

Admin’s role

credentials[].orgId

Number

Organization / Department ID

privileges

Array

Array of admin’s privileges

failedAttempts

Number

Number of failed attempts to log in

failedDate

String

Date of last failed attempt to log in

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 357
+
+{"id":912,"type":"SAS","status":"Active","forename":"client-admin-2048","surname":"client-admin-2048","email":"2049aa@nobody.sectigo.com","phone":"+123456789","created":"2025-08-15","modified":"2025-08-15","credentials":[{"role":"DRAO_SSL","orgId":1139}],"activeState":"Active","privileges":["allowManageDomains"],"failedAttempts":0,"activeStatus":"ACTIVE"}
+
+
+
+
+
+

Get available roles

+
+

Get roles the administrator can assign to other administrators who they may update.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

isForEdit

Optional flag indicating that roles are intended for edit another admin.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/roles?isForEdit=false' -i -X GET \
+    -H 'login: admin_customer2107' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2107' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Admin roles. Possible values: 'MRAO', 'RAO_SSL', 'RAO_SMIME', 'RAO_DEVICE', 'RAO_CS', 'DRAO_SSL', 'DRAO_SMIME', 'DRAO_DEVICE', and 'DRAO_CS'

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 100
+
+["MRAO","RAO_SSL","RAO_SMIME","RAO_CS","RAO_DEVICE","DRAO_SSL","DRAO_SMIME","DRAO_CS","DRAO_DEVICE"]
+
+
+
+
+
+

Get available privileges

+
+

Get privileges the administrator can assign to other administrators who they may update.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

role

Admin’s role. Multiple roles can be provided.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/privileges?role=RAO_SSL&role=RAO_SMIME' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2068' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2068' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].name

String

Admin privileges. Possible names: + 'allowCreate' - Add peer administrator; + 'allowEdit' - Edit peer administrator; + 'allowDelete' - Delete peer administrator; + 'allowDCV' - Manage domain validations; + 'autoApproveCertificates' - Automatically approve certificate requests; + 'allowMsAdDiscovery' - MS agent management; + 'allowKeyVault' - Download keys from Sectigo Key Vault; + 'approveDomainDelegation' - Approve domain delegation; + 'allowManageDomains' - Manage domains; + 'sslRequest' - Request SSL certificates; + 'sslRenew' - Renew SSL certificates; + 'sslReplace' - Replace SSL certificates; + 'sslRevoke' - Revoke SSL certificates; + 'sslApprove' - Manage SSL certificate requests; + 'sslManage' - Manage SSL certificates; + 'clientCertRequest' - Request client certificates; + 'clientCertRevoke' - Revoke client certificates; + 'clientCertManage' - Manage client certificates; + 'csRequest' - Request code signing certificates; + 'csRevoke' - Revoke code signing certificates; + 'csManage' - Manage code signing certificates; + 'deviceRequest' - Request device certificates; + 'deviceRenew' - Renew device certificates; + 'deviceReplace' - Replace device certificates; + 'deviceRevoke' - Revoke device certificates; + 'deviceApprove' - Manage device certificate requests; + 'deviceManage' - Manage device certificates; + 'editOrganizationAndDepartment' - Edit organizations & departments; + 'addOrganizationAndDepartments' - Add organizations & departments; + 'addDepartments' - Add departments; + 'editDepartments' - Edit departments; + 'orgValidationManager' - Manage organization validations; + 'viewUsage' - View usage; + 'viewSubscriptions' - View subscriptions; + 'manageSubscriptions' - Manage subscriptions; + 'allowSslAutoApprove' - Deprecated (falls back to 'autoApproveCertificates'). Please, use 'autoApproveCertificates' privilege instead.; + 'wsApiUseOnly' - Deprecated (replaced with new admin type - 'API').

[].description

String

Description for privilege.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 1330
+
+[{"name":"addDepartments","description":"Add departments"},{"name":"allowCreate","description":"Add peer administrator"},{"name":"allowDelete","description":"Delete peer administrator"},{"name":"allowEdit","description":"Edit peer administrator"},{"name":"allowManageDomains","description":"Manage domains"},{"name":"approveDomainDelegation","description":"Approve domain delegation"},{"name":"autoApproveCertificates","description":"Automatically approve certificate requests"},{"name":"clientCertManage","description":"Manage client certificates"},{"name":"clientCertRequest","description":"Request client certificates"},{"name":"clientCertRevoke","description":"Revoke client certificates"},{"name":"editDepartments","description":"Edit departments"},{"name":"manageSubscriptions","description":"Manage subscriptions"},{"name":"orgValidationManager","description":"Manage organization validations"},{"name":"sslApprove","description":"Manage SSL certificate requests"},{"name":"sslRenew","description":"Renew SSL certificates"},{"name":"sslReplace","description":"Replace SSL certificates"},{"name":"sslRequest","description":"Request SSL certificates"},{"name":"sslRevoke","description":"Revoke SSL certificates"},{"name":"viewSubscriptions","description":"View subscriptions"},{"name":"viewUsage","description":"View usage"}]
+
+
+
+
+
+

Get list of Identity Providers

+
+

Get list of available Identity Providers that can be assigned to Standard, IdP administrators and IdP templates.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/idp' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2121' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2121' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of customer’s IdP

[].id

Number

IdP ID

[].name

String

IdP name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 29
+
+[{"id":90,"name":"Test Idp"}]
+
+
+
+
+
+
+

Manage Administrators

+
+

Supported administrator types:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription

STANDARD

Admin with the ability to log in with username/password, authentication certificate, and/or IdP. Standard can be used with APIs if the password or authentication certificate is set.

API

Admin with the ability to use API only with username/password or authentication certificate.

IDP

Admin with the ability to log in to the UI only via IdP. They cannot use an API.

SAS

Admin created externally in Sectigo Authentication Service.

+
+

Create administrator

+
+

Create administrator account. This method supports different admin types (see "Supported administrator types").

+
+
+
+

Create standard administrator

+
+

Create Standard administrator account. +Note: This administrator type will be used by default if type is not specified in request.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'STANDARD'

[]

login

String

Administrator login (mandatory)

[Must match the regular expression ^([a-zA-Z0-9\!\@\_\.\-\+\'])*$, Size must be between 3 and 128 inclusive]

password

String

Password (mandatory)

[Maximum length is 64 characters or can be empty]

certificateSerialNumber

String

Authentication Certificate Serial Number

[Must match the regular expression (0x)?[0-9a-fA-F:]+]

forename

String

Forename (mandatory)

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname (mandatory)

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

identityProviderId

Number

Identifier of Identity Provider. Please use the "Get list of identity providers" API to get available IdPs. Can be specified if authentication via IdP is required.

[Must be at least 1]

idpPersonId

String

Person Identifier for given Identity Provider (EPPN). Mandatory in case 'identityProviderId' is specified.

[Maximum length is 256 characters or can be empty]

email

String

Email address (mandatory)

[Must be a well-formed email address, Must not be null, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must not be empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1854' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1854' \
+    -H 'Accept: application/json' \
+    -d '{"type":"STANDARD","login":"admin","email":"standard@test.test","forename":"Admin","surname":"Admin","certificateSerialNumber":"123456789AB","password":"Password#1234","privileges":["allowCreate","allowDelete","allowEdit"],"credentials":[{"role":"RAO_SSL","orgId":1088}],"identityProviderId":56,"idpPersonId":"eppn@test","activeStatus":"ACTIVE"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created admin

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/admin/v1/824
+
+
+
+
+
+

Create API administrator

+
+

Create API administrator account.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'API'

[]

login

String

Administrator login (mandatory)

[Must match the regular expression ^([a-zA-Z0-9\!\@\_\.\-\+\'])*$, Size must be between 3 and 128 inclusive]

password

String

Password (mandatory)

[Maximum length is 64 characters or can be empty]

certificateSerialNumber

String

Authentication Certificate Serial Number

[Must match the regular expression (0x)?[0-9a-fA-F:]+]

forename

String

Forename (mandatory)

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname (mandatory)

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

email

String

Email address (mandatory)

[Must be a well-formed email address, Must not be null, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must not be empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1865' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1865' \
+    -H 'Accept: application/json' \
+    -d '{"type":"API","login":"admin","email":"api@test.test","forename":"Admin","surname":"Admin","certificateSerialNumber":"123456789AB","password":"Password#1234","privileges":["allowCreate","allowDelete","allowEdit"],"credentials":[{"role":"RAO_SSL","orgId":1091}],"activeStatus":"ACTIVE"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created admin

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/admin/v1/830
+
+
+
+
+
+

Create IDP administrator

+
+

Create IdP administrator account that is not linked to an IdP Template. After admin is created, login invitation email is sent automatically to the specified admin’s email.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'IDP'

[]

forename

String

Forename

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

email

String

Email address (mandatory)

[Must be a well-formed email address, Must not be null, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must not be empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1876' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1876' \
+    -H 'Accept: application/json' \
+    -d '{"type":"IDP","email":"idp@test.test","forename":"Admin","surname":"Admin","privileges":["allowCreate","allowDelete","allowEdit"],"credentials":[{"role":"RAO_SSL","orgId":1094}],"activeStatus":"ACTIVE"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created admin

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/admin/v1/834
+
+
+
+
+
+

Create SAS administrator

+
+

Create Sectigo Authentication Service administrator account.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'SAS'

[]

forename

String

Forename

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

email

String

Email address (mandatory)

[Must be a well-formed email address, Must not be null, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must not be empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1883' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1883' \
+    -H 'Accept: application/json' \
+    -d '{"type":"SAS","email":"sas@test.test","forename":"Admin","surname":"Admin","privileges":["allowCreate","allowDelete","allowEdit"],"credentials":[{"role":"RAO_SSL","orgId":1096}],"activeStatus":"ACTIVE"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created admin

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/admin/v1/838
+
+
+
+
+
+

Update administrator

+
+

Update administrator account. Fields that are not changed can be omitted. +This method also allows you to change admin type, available transitions are:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Current TypeAllowed Types

STANDARD

API, IDP, SAS

API

STANDARD

IDP

STANDARD, SAS

SAS

STANDARD

+
+

Note: Changing of admin type may require additional fields to be specified.

+
+
+
+

Update standard administrator

+
+

Update Standard administrator account.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'STANDARD'

[]

login

String

Administrator login

[Must be null or not blank, Must match the regular expression ^([a-zA-Z0-9\!\@\_\.\-\+\'])*$, Size must be between 3 and 128 inclusive]

password

String

Password (mandatory)

[Maximum length is 64 characters or can be empty]

certificateSerialNumber

String

Authentication Certificate Serial Number

[Must match the regular expression (0x)?[0-9a-fA-F:]+]

forename

String

Forename

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

identityProviderId

Number

Identifier of Identity Provider. Please use the "Get list of identity providers" API to get available IdPs. Can be specified if authentication via IdP is required.

[Must be at least 1]

idpPersonId

String

Person Identifier for given Identity Provider (EPPN). Mandatory in case 'identityProviderId' is specified.

[Maximum length is 256 characters or can be empty]

email

String

Email address

[Must be a well-formed email address, Must be null or not blank, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must be null or not empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/959' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2147' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2147' \
+    -H 'Accept: application/json' \
+    -d '{"type":"STANDARD","login":"rao","email":"2155aa@nobody.sectigo.com","forename":"RAO SSL","surname":"Admin","telephone":"+1 (888) 266-6361","certificateSerialNumber":"123456789AB","password":"Password#1234","privileges":["allowCreate","allowEdit","allowDelete"],"credentials":[{"role":"RAO_SSL","orgId":1168}],"identityProviderId":94,"idpPersonId":"new.eppn@test","activeStatus":"SUSPENDED"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Update API administrator

+
+

Update API administrator account.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'API'

[]

login

String

Administrator login

[Must be null or not blank, Must match the regular expression ^([a-zA-Z0-9\!\@\_\.\-\+\'])*$, Size must be between 3 and 128 inclusive]

password

String

Password

[Maximum length is 64 characters or can be empty]

certificateSerialNumber

String

Authentication Certificate Serial Number

[Must match the regular expression (0x)?[0-9a-fA-F:]+]

forename

String

Forename

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

email

String

Email address

[Must be a well-formed email address, Must be null or not blank, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must be null or not empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/965' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2160' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2160' \
+    -H 'Accept: application/json' \
+    -d '{"type":"API","login":"rao","email":"2168aa@nobody.sectigo.com","forename":"RAO SSL","surname":"Admin","telephone":"+1 (888) 266-6361","certificateSerialNumber":"123456789AB","password":"Password#1234","privileges":["allowCreate","allowEdit","allowDelete"],"credentials":[{"role":"RAO_SSL","orgId":1171}],"activeStatus":"SUSPENDED"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Update IDP administrator

+
+

Update IdP administrator account.

+
+
+

Note: If IdP administrator has IdP template assigned, then modification is limited to the personal fields only; +privileges, credentials and Identity Provider are managed by the parent IdP template.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'IDP'

[]

forename

String

Forename

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

identityProviderId

Number

Identifier of Identity Provider. Please use the "Get list of identity providers" API to get available IdPs. Can be used to change assigned Identity Provider for activated IdP administrators.

[Must be at least 1]

idpPersonId

String

Person Identifier for given Identity Provider (EPPN). Mandatory in case 'identityProviderId' is specified.

[Maximum length is 256 characters or can be empty]

email

String

Email address

[Must be a well-formed email address, Must be null or not blank, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must be null or not empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/971' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2173' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2173' \
+    -H 'Accept: application/json' \
+    -d '{"type":"IDP","email":"2181aa@nobody.sectigo.com","forename":"RAO SSL","surname":"Admin","telephone":"+1 (888) 266-6361","privileges":["allowCreate","allowEdit","allowDelete"],"credentials":[{"role":"RAO_SSL","orgId":1174}],"activeStatus":"SUSPENDED"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Update SAS administrator

+
+

Update Sectigo Authentication Service administrator account.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

type

String

Administrator type. 'SAS'

[]

forename

String

Forename

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

surname

String

Surname

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

email

String

Email address

[Must be a well-formed email address, Must be null or not blank, Maximum length is 128 characters or can be empty]

title

String

Title or Position

[Maximum length is 64 characters or can be empty]

telephone

String

Telephone Number

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

street

String

Street Address

[Maximum length is 128 characters or can be empty]

locality

String

Locality name

[Maximum length is 128 characters or can be empty]

state

String

State name

[Maximum length is 128 characters or can be empty]

postalCode

String

Postal Code

[Must match the regular expression ^[a-zA-Z0-9\s-]{0,10}$, Maximum length is 40 characters or can be empty]

country

String

Country

[Maximum length is 2 characters or can be empty]

relationship

String

Administrator’s relationship to the company

[Maximum length is 256 characters or can be empty]

privileges

Array

Privileges to assign. In order to get list of available privileges, please use the "Get available privileges" API.

[]

credentials.[]

Array

Credentials to assign. In order to get list of available roles, please use the "Get available roles" API.

[Must be null or not empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization / department ID

[]

activeStatus

String

Allowed values: ACTIVE, SUSPENDED

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/975' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2182' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2182' \
+    -H 'Accept: application/json' \
+    -d '{"type":"SAS","email":"2190aa@nobody.sectigo.com","forename":"RAO SSL","surname":"Admin","telephone":"+1 (888) 266-6361","privileges":["allowCreate","allowEdit","allowDelete"],"credentials":[{"role":"RAO_SSL","orgId":1176}],"activeStatus":"SUSPENDED"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+ +
+

This method removes the link to IdP template for IdP administrator, thus admin will no longer be managed by it.

+
+
+ + + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}/unlink
ParameterDescription

id

ID of IdP admin to unlink from IdP template.

+
+
+ +
+
+
$ curl 'https://cert-manager.com/api/admin/v1/954/unlink' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2137' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2137' \
+    -H 'Accept: application/json'
+
+
+
+
+ +
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete administrator

+
+

Delete administrator account.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin/v1/{id}
ParameterDescription

id

ID of admin being deleted

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + +
ParameterDescription

replacingRequesterId

Optional, specifies ID of the client administrator to be assigned as certificate requester instead of the one being deleted. If omitted, currently assigned requester is retained. The replacing requester should have type other than IdP Template and have Id that differs from Id of the client administrator being deleted. Use respective list API method with necessary filtering options to get suitable client administrators.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/886?replacingRequesterId=885' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1983' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1983'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Get password state

+
+

State of administrator password. Available for Standard and API administrators.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/password' -i -X GET \
+    -H 'login: admin_customer2061' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2061' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

state

String

Admin password state. Possible values: 'ALIVE', 'EXPIRED' and 'NEVER_EXPIRE'

expirationDate

String

Password expiration date.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 47
+
+{"expirationDate":"2025-11-15","state":"ALIVE"}
+
+
+
+
+
+

Change password

+
+

Change of administrator password. Available for Standard and API administrators.

+
+
+
Success case
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/changepassword' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1840' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1840' \
+    -H 'Accept: application/json' \
+    -d '{"newPassword":"newPass122345"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
Failed case
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin/v1/changepassword' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1847' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1847' \
+    -H 'Accept: application/json' \
+    -d '{"newPassword":"new"}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

code

Number

Code of error if error has occurred

description

String

Error message

+
+
+
Example response
+
+
+
HTTP/1.1 400 Bad Request
+Content-Type: application/json
+Content-Length: 209
+
+{"code":-7306,"description":"Password policy violated: Password must contain 1 or more uppercase characters. Password must contain 1 or more digit characters. Password must be 8 or more characters in length."}
+
+
+
+
+
+
+
+
+
+

Template Administrators

+
+
+

Supported administrator types:

+
+ ++++ + + + + + + + + + + + + +
TypeDescription

IDP_TEMPLATE

IdP admins are created automatically from a template. The IdP attribute mapping controls which template an admin will be linked to.

+
+

View IdP templates

+
+

List IdP templates

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

name

Filter by name

orgId

Filter by organization ID

identityProviderId

Filter by Identity Provider ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin-template/v1?size=10&position=0' -i -X GET \
+    -H 'login: admin_customer2397' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2397'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested client admins

[].id

Number

IdP template admin ID

[].name

String

IdP template name

[].identityProviderId

Number

ID of assigned Identity Provider.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 129
+
+[{"id":1077,"name":"client-admin-2403","identityProviderId":126},{"id":1076,"name":"client-admin-2402","identityProviderId":126}]
+
+
+
+
+
+

Get IdP template details

+
+

Get detailed information about IdP template.

+
+
+
+
+

Manage IdP templates

+
+

Create IdP template

+
+

Create IdP Template.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Template name.

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Must not be blank, Maximum length is 64 characters or can be empty]

privileges

Array

Privileges that will be assigned to the admin, automatically created by this template. In order to get available privileges, please use "Get available privileges" method from the "Administrators" API.

[]

credentials.[]

Array

Credentials that will be assigned to the admin, automatically created by this template. In order to get available roles, please use "Get available roles" method from the "Administrators" API.

[Must not be empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization ID

[]

identityProviderId

Number

Identity Provider ID that IdP Template can be used with.

[Must be at least 1]

idpMappingRules

Array

Mapping rules that should be applied in order to check whether user’s IdP attributes match the template.Should always include "groups" attribute.

[Must not be empty]

idpMappingRules.[].attribute

String

IdP attribute name.

[]

idpMappingRules.[].matchType

String

Matching type. Available options: MATCHES (default), CONTAINS.

[]

idpMappingRules.[].values

Array

Allowed values that IdP attribute value should match in whole or in part, depending of specified "matchType". Note: in case of collection attribute, rule is applied on its items - if at least one meets the rule, it will be considered as matched.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin-template/v1/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2281' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2281' \
+    -H 'Accept: application/json' \
+    -d '{"name":"RAO SSL IdP Template","privileges":["editOrganizationAndDepartment","autoApproveCertificates"],"credentials":[{"role":"RAO_SSL","orgId":1201}],"identityProviderId":109,"idpMappingRules":[{"attribute":"groups","matchType":"MATCHES","values":["RAO SSL"]}]}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created IdP Template admin.

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/admin-template/v1/1019
+
+
+
+
+
+

Update IdP template

+
+

Update IdP Template. Fields that are not changed can be omitted in request. +Please note that requested changes (except name) are automatically applied to all IdP admins assigned to this template. +In order to get a list of administrators that are currently assigned to this template, +please use "List administrators" method from the "Administrators" API with filter by "templateId" parameter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin-template/v1/{id}
ParameterDescription

id

ID of IdP admin template being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Template name.

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Maximum length is 64 characters or can be empty]

privileges

Array

Privileges that will be assigned to the admin, automatically created by this template. In order to get available privileges, please use "Get available privileges" method from the "Administrators" API.

[]

credentials.[]

Array

Credentials that will be assigned to the admin, automatically created by this template. In order to get available roles, please use "Get available roles" method from the "Administrators" API.

[Must be null or not empty]

credentials.[].role

String

Role

[]

credentials.[].orgId

Number

Organization ID

[]

identityProviderId

Number

Identity Provider ID that IdP Template can be used with.

[Must be at least 1]

idpMappingRules

Array

Mapping rules that should be applied in order to check whether user’s IdP attributes match the template.Should always include "groups" attribute.

[Must be null or not empty]

idpMappingRules.[].attribute

String

IdP attribute name.

[]

idpMappingRules.[].matchType

String

Matching type. Available options: MATCHES (default), CONTAINS.

[]

idpMappingRules.[].values

Array

Allowed values that IdP attribute value should match in whole or in part, depending of specified "matchType". Note: in case of collection attribute, rule is applied on its items - if at least one meets the rule, it will be considered as matched.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin-template/v1/1080' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2404' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2404' \
+    -H 'Accept: application/json' \
+    -d '{"name":"Updated client-admin-2409","privileges":["allowCreate","allowEdit","allowDelete"],"credentials":[{"role":"RAO_SSL","orgId":1220}],"identityProviderId":127,"idpMappingRules":[{"attribute":"groups","matchType":"MATCHES","values":["RAO SSL"]}]}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete IdP template

+
+

Delete IdP template. By default, all related administrators will be deleted automatically with the template. +It is also possible to unlink all related administrators from this template. +In order to get a list of administrators that are currently assigned to this template, +please use "List administrators" method from the "Administrators" API with filter by "templateId" parameter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/admin-template/v1/{id}
ParameterDescription

id

ID of IdP template being deleted

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

relatedAdminsAction

Option that specify required action for the related IdP admins that were created based on this template and still assigned to it. Allowed values: delete, unlink. Default value is 'unlink', which means that assigned admins will be unlinked from this template and will no longer be managed by it. When 'delete' action is specified, then related admins will be deleted together with this template.

replacingRequesterId

Optional, specifies ID of the client administrator to be assigned as certificate requester instead of those being deleted. If omitted, currently assigned requesters are retained. Has no effect if 'unlink' or no value is passed to 'relatedAdminsAction' request parameter. The replacing requester should have type other than IdP Template and have no parent template or have parent template whose Id differs from Id of the template being deleted. Use respective list API method with necessary filtering options to get suitable client administrators.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/admin-template/v1/1054?relatedAdminsAction=DELETE&replacingRequesterId=1053' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer2349' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst2349'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+
+
+

Persons

+
+
+

View persons

+
+

List persons

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

name

Person name (url encoded)

organizationId

Organization ID

email

Person email

commonName

Person commonName

phone

Person phone

secondaryEmail

Person Secondary Email

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1?position=0&size=10&name=Tester&organizationId=3218&email=21583_.email%40domain.com&commonName=Tester&secondaryEmail=alt1.email%40domain.com&phone=3456789' -i -X GET \
+    -H 'login: admin_customer21580' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of persons

[].id

Number

Person ID

[].organizationId

Number

Organization ID

[].email

String

Person e-mail

[].firstName

String

Person firstname

[].lastName

String

Person lastname

[].middleName

String

Person middlename

[].validationType

String

Person validation type

[].phone

String

Person Phone

[].commonName

String

Person CommonName

[].secondaryEmails

Array

Person Secondary Emails

[].eppn

String

Person EPPN

[].upn

String

Person UPN

[].created

String

Created date

[].createdBy

String

Name of the administrator who added the person

[].modified

String

Modified date

[].modifiedBy

String

Name of the administrator who last modified the person

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 351
+
+[{"id":165,"firstName":"Tester","middleName":"","lastName":"","email":"21583_.email@domain.com","organizationId":3218,"validationType":"STANDARD","phone":"123456789","secondaryEmails":["alt1.email@domain.com","alt2.email@domain.com"],"commonName":"Tester","eppn":"","upn":"","created":"2025-08-15T09:22:52.924Z","modified":"2025-08-15T09:22:52.935Z"}]
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Contains total number of persons available according to the filtering applied

+
+
+
+

Find person by email

+
+

Will return ID for a person with given email.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/id/byEmail/{email}
ParameterDescription

email

Person e-mail. Must be formatted as valid e-mail string. Also might need to be properly encoded as required by URL syntax standard. For example, the '@' character should be replaced with the %40 code, '.' - with %2E and so on.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/id/byEmail/21562_.email@domain.com' -i -X GET \
+    -H 'login: admin_customer21559' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

personId

Number

Person ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Disposition: inline;filename=f.txt
+Content-Type: application/json
+Content-Length: 16
+
+{"personId":162}
+
+
+
+
+
+

Get person details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/{id}
ParameterDescription

id

Person ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/161' -i -X GET \
+    -H 'login: admin_customer21552' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json;charset=UTF-8'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Person ID

organizationId

Number

Organization ID

email

String

Person e-mail

firstName

String

Person firstname

lastName

String

Person lastname

middleName

String

Person middlename

validationType

String

Person validation type. Values: [STANDARD, HIGH]

phone

String

Person Phone

commonName

String

Person CommonName

secondaryEmails

Array

Person Secondary Emails

eppn

String

Person EPPN

upn

String

Person UPN

created

String

Created date

createdBy

String

Name of the administrator who added the person

modified

String

Modified date

modifiedBy

String

Name of the administrator who last modified the person

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 349
+
+{"id":161,"firstName":"Tester","middleName":"","lastName":"","email":"21555_.email@domain.com","organizationId":3210,"validationType":"STANDARD","phone":"123456789","secondaryEmails":["alt1.email@domain.com","alt2.email@domain.com"],"commonName":"Tester","eppn":"","upn":"","created":"2025-08-15T09:22:50.958Z","modified":"2025-08-15T09:22:50.974Z"}
+
+
+
+
+
+
+

Manage persons

+
+

Create person

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

firstName

String

Person’s first name

[Must not be blank, Maximum length is 64 characters or can be empty]

middleName

String

Person’s middle name

[Maximum length is 64 characters or can be empty]

lastName

String

Person’s last name

[Must not be blank, Maximum length is 64 characters or can be empty]

email

String

Person’s email

[Must be a well-formed email address, Must not be empty, Maximum length is 128 characters or can be empty]

validationType

String

Person’s validation type. Values: [STANDARD, HIGH]

[Must not be null]

organizationId

Number

Organization ID

[Must be at least 1, Must not be null]

phone

String

Person phone

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

commonName

String

Person commonName

[Maximum length is 64 characters or can be empty]

secondaryEmails

Array

Person Secondary Emails

[]

eppn

String

Person EPPN

[Maximum length is 128 characters or can be empty]

upn

String

Person UPN

[Maximum length is 256 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21489' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"firstName":"First Name","middleName":"Middle Name","lastName":"Last Name","email":"test@email.com","organizationId":3192,"validationType":"STANDARD","phone":"1235","secondaryEmails":["alt1.email@domain.com","alt2.email@domain.com"],"commonName":"Tester123","eppn":"","upn":null}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created person

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/person/v1/151
+
+
+
+
+
+

Update person

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/{id}
ParameterDescription

id

Person ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

firstName

String

Person’s first name

[Must be null or not blank, Maximum length is 64 characters or can be empty]

middleName

String

Person’s middle name

[Maximum length is 64 characters or can be empty]

lastName

String

Person’s last name

[Must be null or not blank, Maximum length is 64 characters or can be empty]

email

String

Person’s email

[Must be a well-formed email address, Must be null or not blank, Maximum length is 128 characters or can be empty]

validationType

String

Person’s validation type. Values: [STANDARD, HIGH]

[]

organizationId

Number

Organization ID

[Must be at least 1]

phone

String

Person phone

[Must match the regular expression [#|0-9|\(|\)|\-|\+| x]*, Maximum length is 32 characters or can be empty]

commonName

String

Person commonName

[Must be null or not blank, Maximum length is 64 characters or can be empty]

secondaryEmails

Array

Person Secondary Emails

[]

eppn

String

Person EPPN

[Maximum length is 128 characters or can be empty]

upn

String

Person UPN

[Maximum length is 256 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/169' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21608' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"firstName":"First Name","middleName":"Middle Name","lastName":"Last Name","email":"test@email.com","organizationId":3226,"validationType":"STANDARD","phone":"1235","secondaryEmails":["alt1.email@domain.com","alt2.email@domain.com"],"commonName":"Tester123","eppn":"","upn":null}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete person

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/{id}
ParameterDescription

id

Person ID being deleted

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/160' -i -X DELETE \
+    -H 'login: admin_customer21545' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Import private key

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v2/{personId}/import-key
ParameterDescription

personId

Person ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

p12

String

Base64 encoded pkcs12 file

[Must not be empty]

password

String

Password to access pkcs12 file

Optional

customFields

Array

An array of custom fields if required

Optional

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v2/139/import-key' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21424' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"p12":"MIIc9AIBAzCCHK4GCSqGSIb3DQEHAaCCHJ8EghybMIIclzCCBXwGCSqGSIb3DQEHAaCCBW0EggVpMIIFZTCCBWEGCyqGSIb3DQEMCgECoIIE+jCCBPYwKAYKKoZIhvcNAQwBAzAaBBRkrpqy0Rl09IE89cMzT+8i0+lhOAICBAAEggTIXoY6WMPXG7P4x888tra7Y49A4GYbv5szwUKjjddvux14IPB8yz0MPeAD4TO/5Qmp4ERF3V/TF6YBL5MxQw+IEHDF3r1P3drvdd/Ku4R/us6XSHfphqGHT9BVmP+qtZOLOkhe3r7NNLVETNw6GZNQPKRKMf6VbLJE9VpJO4evI23wSZxqUnfKZpkGYtoh+jIBLxV31erwxa4/ffBeVlFYPw+MNj38lMn7Q3Xr5vys6PmLBtUgRTnbER/jXxbo9vXP6pJobupZpwfQRabzqm3Gj7qk51NNAfj8I7hXG2u8VcCAB+LJuj6CqGf13zhkEcibjI+JlqHKI7FfzHFZFLNURrRciGpd6WxT4R27GTPUqiNwmK5XU+GTwgO/NNXQCQTFKJ3HZ1LJj4i3hbUBBAzABTD7OB7Zns6vdSzHx447Qc9hY2g907ZhluLhyAxKNSkZXrRArJKadDNYV+eD9zdY80/itKQGKqR0haFkZW1NMEs2ZQsWAPgMcvdyxkU47+QvGH7ETBnpWGJFVRH/x4juLo46y8IQ9/umiyxYmJ9q9TEy7wm/Fg4UqG9JXckXNN5Apsk4Y2Me7I+uPXFeHbmifzgngMRvrCb+2NppOaPrvCPFCbknVq3091dLHDd2Ajd0vTtP/467YI0xPyr+Yzx6RcFm7oFNtx5Z8JRKpJT4RFF6ZVMkMsKAozsAHJsbtCB9JBE7gRJzm6HPEVSqwZ+49CtIyJ5JTuzDV/DB0DDg39y+27NpAL/Gj4Em4wcEhdyGpnsAhMO+FNMLRDPQGDbdOhdrz3eKIVy3wqxIiJb6VEOuV+J8cLxF7rvqctj+tGQP5VVxsXSHJHQCFPeo5GHlBk/GqG/ZIbxqJdYag+Bpyf7C/XKd85VriiBO949Jio4HxDe/C62j/RwqbTeUoJ7FU/0JPsGhxkloPbmLNmoXv9aJlewwjYDgqSsHfjQpVGNopcRiX0X1HPZNMlF4XpZ8lEGK+RAbYJnHhp/RQKe80tKg4NY7WYmB9cHYhvax8a0VMuKmYlzpugHJRQlE0q+i3Gzh8nPeEjN4HX+RrwXBNbHDBtuUYdNBh6vSvdD64w1Jw22zF8RsfN5vRCDsBM64bwdWlUW7LYhV6eiqrle8X6JIEUUl2OIQLwUCL6m0LzUwzUh902+iEAZi28QnNSQB0bVoxfnCnN8P978+B5oVDhsbRjPhplSjD7BvSSBPiTpjesRFGIqPkzAMXlfbOszyXRwEErtwDNlqp/qj110hDxskuaV154HDcZLSyqJGvs/GxooBCNIDdxI75eATwnwMNHHxo+gebj9crLycA1AkHRr3/iFHbDZN0Hd2kIm7Z+beD7DmBCLFY8AcfeQBYmCxo4BLHVBIvr9hlqUxi1zU4KEWFhHgo8/S4qOXfR99c7LvfV3rOaE4qEyj7cxJean1smnEp9uc0chUXGbL+MsgrkAXOfafGNkxmAflwEh/WyhtsVjU9saDvWzRN3sJnkwlhuqBfqGfV0402TmHYpaGzyOeHqn7Wir/Nn7F5P0BmgnSmJIIG0bKE44hTJcvppcEju+qmyJUCM9NmahMSmwkZLTWAx9mhZDe2OqC6d4yqIRK9I/gHwMLqhlFuSOzwhDnpb+qwVY3QMw+MVQwIwYJKoZIhvcNAQkVMRYEFI3YZBRdwYCDyiA9uLphQZnGCtx2MC0GCSqGSIb3DQEJFDEgHh4AYQBkAG0AaQBuAEAAYwBjAG0AcQBhAC4AYwBvAG0wghcTBgkqhkiG9w0BBwagghcEMIIXAAIBADCCFvkGCSqGSIb3DQEHATAoBgoqhkiG9w0BDAEGMBoEFA6laLzuLYF2mkOyxGvWfC04PwIOAgIEAICCFsCgCj9qK1Vzx9McX8htHPTeg2LiplMfbMQhCGotrhNAq06NFlKSwIjkLnLijveF3oosyZ4mTYuNBy4Wqg9Q7uZpne5hWTKD87X4NUn1cSB3Xq8ATRTA6pVAF6uZCDQwLBtmUBaRCsIPRNjukLqAxvyQavSqAHmn1+v3Na0BIc8x4RRN6RxiJnMiHEAhwQecx8WT802xGMyXvga06N3fXYGr0w0sVMHckZm0yagJObQ8AMQci9YdiFJsUtfrL+SGkfWgG0SyG3PP77ZFALVciwtMs82Y+yPDC6ZJVsas15UqAzbWGtWyqy459fVpIUu0LNo4Mqg2UeG3toZTcBYF1SfnYalbRsPSN3miL9NQJmluTWv0l/jm3YZETDpeRsbgpm2wuDvkBGxzzS8mwlmwenjKXfPD8uGpbyLX7oxP0m0a+zrQvkApbNI2ZI7Ebgo/JjNOhr9JWXo5hEjOgNh+dRv+gqwKgNy0bxEbncHkQc/xxMpDGfyUpHNEFvZLWdMwrz+l1Xy+3lI8jHsyZ3uMj8e93ADQnWuMSPhGwihFqbTU0HwIGiQt0DgNK87jFxlc+/iZ5QEh6T62jTR7jXY+sVQ1PfTBWQ0UwGYhF1VavFpPzNa/UmTppo8mV8eGNfChcUn0nk1O5jQQOV7rx5uSmKFKgGUP2upTKkikIePrhjqIMXzFgalmMQ/loBimxi/5fEMlZIVb9YAx5cBNVtx6ZdwsJ4J72WiAuLYkIialoVfCeLHr3v5Sk1oZbwT/mFxv85rNFGobD3LpSU87iJPghAQInKJyWHgaoRzyTubHqgnKJRrMFEb45FJ/EtTP50XCknQVHW7u/geDMNhAmCCA4KSBuhmWDSs6DnmXiDHaG/Msd4E1o/0X56fbRI+qFr+iaMSWIoXrps/SmuUQC8QTLs9qJ1mESXCLPyhsY9dZRMhtX+7qBRPElC+IKHsVTdmYS4cpANy+adviTipJMlwWvNJm7cgRrOcRdFD7xOsxRX1cICCoEsaRKifzzts6xfOGJRE/1KFi+krlH3zQuVkooky/PWQXjgRKdRJvIUIX3RQNCwmDHeAA9IhmmlXARjJOtRMj/eHOOS93y0dYrsA5Md5p5NTX5FLQHWXF/rSvCD841345T7gF4c0zYYKj9toQ57qExx/TZvdrIQcNPoD80ZQk4YSd9O54f7KxD5uTOPjAmuzvFrrrb6y6Zxh7jU37x0KHJmiwPSa7fYCwzR9zuWwfFXJ+z0ztWWbKE39ZeVWPkM1Dx6il+Pew99ftslUzoglfeU+OMcdd+pQkX2MiTHzGC7gt8krSQqt79HqmgD8iptVc7mW+m3JsyI3xT4hKTssqEZKYy9+t6UTNxSus1iaj1jKo3wieI8odgKzVhEyKxr54qVPDsmlbI+z4HY5/lnmkwV/OIyuVfr76+3EMQ+PhPJcb9z4zHkYkMDbeu5i1vsWvYyg92RfbYSaLbdNDxHnZAjb+bExDnwksariQk5r0C75hvveu2v7+T9meF2EbOPod1lVPJNN7SU0TiptIIfyBFTheha8gwIRUoaMPwfnLiYc/XdDNCEkcoRwUxYb4Cdgxf1kcEzuBJy7dERlKyPibTT9xzoHrQpMm3KgcPIvFXj3fDABcDw23mC16ZEfs/a17N2cfsH+UXHvNiphM/VJIWCHORj1o6gqs6lfV7S5NDEjwNgS1q8zRZF8RGrtbSjlAdyFJ3LlHDAvOAvBsN+OQRR7AB+mJvP+JxDrihDAx9Kggz7qBcTzsyzp7de5eka7ju/D73NBNnalKbvaBMmp5hkDMVvAZGLsgRGK4gEwtAtf5tBb/bQKFtvbwdHs63vh0V/fpRU4v2JWegl8mgexw+vNhRv9Sv93Zpw6PUSMYRYiTF/csOk3aemdUwCBEVyoElOvL1CJX2pKYchYzbKVk+00zLaAWlOhlsBCeVmVnZhi6HirFcUPWmzJS1AEa66feuy6nuJREcUbMLaLpIvjmd44T7oTqzZPFYNIi/9jCtXREp1Lav4z17CUAtGEmaRSwMjoorBjTLGgPF3/+/04MClWf3h4oKLyhtj98ric9r5KDhZRDnYZHCUxBXbkvAo55svvmKopCuB2coB2B8H44DOfc/3wKNk/ud9MzcyD/J9C8pBLGGdjwm70g8DYyoJCBOEuMff1879kQWJblNcIJJAlKf70UfOHpwc4Nw+MD9e66TR3LWV74SqUqSRvtGrtWRGernQnPRoEe1/DlaxlUxDESIyL9FzrcXROQRXCuufspczS2cUucWCESbJAUwVVShCTgRKv3HhTakkbw4U5dy89kLx9VWX/Qj0NPJYOaelef7EI+PLeYqxhwHNDbicXih4dE8L9ImsyzybV4tpO9cBxTQVYJkAPo2DWGB8UFjvbZBq8hxOeQ/GRx+bSKn7nm21c4t6DDH3Sp+jSNqi3851StlLP/TtspQDk8fq9/+WgcAEGlRCloW+8M/mAfh6ZYTRNJoqN3Ey4WkRMzPc6ZTCBzcqagAizj3CZreLoYPBCKdwv01BqqJM5q+FbfVzk5k8AqWDlotcNW0O4q4vl8mk8AmHDP5J/zy8Co5S2vfqD65vZsGdbOSjES1u6WMyltSnrIxjXdVzo3xriFt33aNc/wW3d12ZGoD0dHO6fJJw1QSWlVJqmZVWGQBjouz3o15V9f3GVJu812P1R4BKQCqz8M288LrD9gOTUrlUR+kXHg0Q7tHDqLTkGHZ2wV4gJZ8PQzoXn4tthqH8fbkHFIXDUyLAg6CrGxaJX9KCRzJ7WeLpTmJf/ljXbwySpI/zkFvK9EJT0tmEfsxUXnzzJLpnmlr3f/gkXn9TYkzB9S3V1yIvsk2IaDh0thZC2RNnbT1A9i4OvNTnAL8JnTkW3t2GB7BLU5bseHUnsdec2fitddaCPcOWmnPO33KoJ7bDRJun1l7zjJP5ZntShAdEJRUHOaAyTaY2Jm4PPm7hrgcVdltNT+4PiMkv9smqNrbovOhmGyYETyS9CxPqaS1iLn3RLkp6HiQTi5xekJXmyZl5ya/DhC3I7kZycV9ca3qEqdvbwF7PMG7Z48kPpTX8PS7gRP83ASjCqTLQROLkHl20+6VgM2+5kPiNA28OFOXrpTWdVnkMH6rHOSxnxMjejeoZEv+5vtvUH4owL5B82FH/fJ9QeDSo6iM+V2v9Xc8nkxl/3HWuRdJWCJ730J49kOheyXpEA9wt9aw5YpPhqJeBPa84kI9JtP5Tlkr3gGAtD/L+jO2Y+jbedQxCffc5R4OVBCndPMFLS+3awrCOP1WNiDQO7+CohGUssFxiRBIBJ948Fx1D7M8ZE8qKliDz+q7EcT5md7nR1d4exUn4aILmwbcwXGKvSiWTJmBGfH7iwSdMbr/ZtCiSfCYMref8ZHG5uO/tGQ/cpCZn67KfsWW6mC35UGnpxnohyyd95rOUSzHkAqi4PJx5tu1LGNXosy4VOSQeQ6ChExKkx2u1j55whlZqaFAsuWA4CxQo1mcny9Qjt8IAFjE2YVbvtvLhMn/lcH3DQUukA6LJPB59udh0lgZDSuQSwRb35+9Q8jWdiCUUbWYJUR5TIwvSngtVt4g2P0eHncD0luHz21F9txsmrql6IOnr5YxU4KptQnU0SssvuYb5jfUO3oOBvvkqCM1vntzgDSKvS53hn0RdH+wY68gltoHsJDFjDVXmobhcHr5ubX3PK11r2uGbDOWApc/h+Bmkwf5rsVn8fCHbnWe+1wQTPSfyujpcC7PffJ/Knmv+vYLAWofMC4TbIY451HIJ4xUHlZfHnaGnnJGf6Hlnpn2P6cFI4AXFNGAzxfAjoNzQowuUQzKxtsEB4mng7hCEzKi5SdEcgTudd6qcMd9Kj1UJFED3gqu7Fo1tjM2EMWlinYOxQxlRSE1lpcd8Y8ZPljOUplZ3P0cSikSLyuGDVkXN94OagUMTNieF+oINFCZsU1aAqf/SxOMh7+tDUNvGj2VTIKa+kBlDTzl51aIGXGwCjj4d7HBJy4cbKH7nW4E2Q6xSKZLYf/UoF6jWao6lO5cpvWFENzGiI6o2fYEYfp2KVyRW+4liMKYT1g5na1NP4Z8VsfEKS6UNzOiiqoMcsiHz2L7qTtvDEL49wYVwuBNm8GHXQ32oZGexIDZz+uhO+nYfVJRRkNh2sKurLgA+NF7jAvP87nejqzwW+aI+SuSppnKe+QBvEfq2IeVaqdpau8qzdlmC3ke3vGC679m+9krN1YNmRdJAxEgs4WF2g1qjKG5hQKVA5uve5dQfFDbHv7y7jkd4zob32A2A1p37qjWESZoRYRtZVjuWduJXB8dG+2tqp8MonINGGbXNLfvahOs+RyiW12c0/17T8x72BSoXOK4DQuABOci0kS7OwjSpKD3joh/nn+Mg6Lmm6Luj+D8i8SB/+kv5+U9oWgbfKNKkz6ilY28px+D8H9P6wLwWFcsiSyO6Sb1vFMY0Wegdt5uXCupf4CVX7d9NEtSYpFKWP8Ufdc6zRvc5LofRJ8noxSpVou0I2+KTFUCfdhIA7LV62JmhC2k61QhN8YllYJcItQc5bgxrSYs/i7dVhwqPDUzbUAcO4q4xuQNtc4asozmjxb2YdidBtE4V2CMf7p//yTA9PGBqDbuv6Yx7RwavTdJW3bLBb+seQKrnYp8zV4u07DaOSOaEVUJfn9fTFt5QiCwOuo5Z2tr7hbn5rwvAA9pm6Br4lys5B5nMFetMp7jKByfZPjF8i1586IjWqgT3B+b7Jrp7qUs/FFmLA5jziVyeVzzGCiw/oXEI1g59Vn8hNPKY3CDXi5vsWVR6zQieA8wM1vXhXM4JdYdsU1fAwDqLf8s+XZND4zveACTdl836QIidvwpUQAkl2AoitI0lE5CNsDClqtY9KIf9TmTkwaWCPXtbQ3A+N/X6abreQn6Tv8w4cu7cu5+v2ebkAIomd9X/BtntSRUreLpZr1+yDOtu6+FNMX2d8c8lSjdO5CekVNXBXaJeyF47oKBmO5oOP3jfvHH7QqW+qXxFcor5x1SJI73eLv+9//z109sWnZ/Fc6aKi1eBe+/SSCisJs8Dh4/W2oLPxhfcMC6hhwvV6yB7dvKZ2eNYeuqR58JS9QwMD4DT3+Qq6Lu7CUcdUkgIQ2/SvnAOaPpRbC1VVoc+fZ/UuBA2DPafWPm0OZzoUA9wrSN5CBCcJLKvY0J2yW9FPuE2wy6CgXtN869K6sEQiHtXqd7hhqVEvmvykjmFFHX2THCEiDd0Jr/Upc7b/tM4tcrEe67AWa7qLCidhQx+lqviyuNgVLDKk73MlwcpFRyrFbZk34qf8H2y5A5DMXfUWr7/5mP4NMbb0b3CTsBWJfB5mu23EBJGifpv5iYGUaDh+n29lvv6X5cyDSJIEpNpDSdQliPaf0einf7EtlkIwVh1JPvxYmL2Xt2w0LXm5SP62zPYfGMYEY5lYW4c5qFSIzKeFjEU+dDA+9tIgtw5XAlkJFIQ2DBl1hIfJczbWJlj5lWX/jDsXk9gdJ13/kU3fRzmdtRhFWPuKWNHI6RJtmKq+6eUldgb7dPbLF8+nVALbSk47+DwqJs6AqKJr/jndJKHtfAdoob/1796/aQUdVHx7Qfzku//gsUEWEvOlUPGloOlBRwf6scvXtcsaGftIc52v6DmHh6A5ehmgdSFpZWoSmQ3BhfbEa2j3grUT9iuv54v4xMi8F1JDDu3tpQG8FwXg6fY2VvKjqHHf6hoS7Xtf5pFrggUbGbDc5gzx5QnPHPHnHuTdnAwcSVwPEh7/9oNe6zYCmhrrbOFEU3QKs7r3wsRe19yjLyyIAfLfrgFUjQ4eS9jNE/NCyDLecqZxg5As72j3uo9HjKnYM0iHC5S57+5IzGVUH7noqFJoyaVE/ATerqP0MqJ1ePaaKpbaE1dx822JWj2rQ0v0UtrsPwEiPMcfDQnxnuv2Norw0UFIm3tOHNQeD2XAcd/epyj43K1EWMc31IS7nPf6EitA0X+ziqFUyLzgqieRTXj9zmDdTzcSnYVdFOQJcMnJSlb9Q7FHfySyJlzGxGUe3ATalnq9psZ1V5ifnzmoAeLvRbdKWguOhPJDK6EemkJSYWvALkrOF+GJkabAhL2PzmOj6VUidgDLhjnwD5ZpmsC7gr8T+Nx1Vmu1ercVRuA66IClIfMijnoq4hjZLOMnvvVLop2yvVh3TMF6qOYQOg1v5Eoz9I0HFu20fn2UZHY2VThdnfCqRkvjYEROIPBRHJVhtPu5ypjS5RWxbVcn90YcBuqVKHDeFgfFPGq7x5fDdAaUNRZW5UZxLR4l9tk8wAAD/oVfoiuPpOXyD2kxqqbnn+UI22Dy0qHjd1JE+w0+WvNb263nTZAjAaM0qB538DHSd2lbsAKHF30C8lBWlsbAfxc8e9t0cqMiZ6R/fVJSwZJVQ507Z/lRVqpgTEFtSLysgBJw1NvUrhQPA1ISu89oEKiwHZDmkWpul7BgY+wYtRuZQBxb7Ji2Ny0y0j+SSBPCDmNZPV+i1Rt0l8YUbu7BH/mGjSMByIaNok4tEEh0pz79G+yZkUeMMUjPWTuiccEg85Jgwh25t62JQu/SnLpPEBjif0dDr3M3sA4jjWX6YxUiGN+Wlry89aoBhIfJFFiNBMtlN42EyonjJfYydof6t/rGeJAlehmfjzMcBRmZEkSUQ6sIqxf04NR3m7ylKv8Wb66DTJaVP5WYHBjuxqQip8hP+gxLb7atHuzV1DFJaU5O/UQ0QDK4FFeNaj1MZRMlAaTh0HBb/DTcZtdH7rDfcX/gft2pbCLwoCetuOiVZGCs0yiyafmUfDsO1QUcJ7PXFO8RGWmN/VXoTb9LJpJLIVGyL361E7IO+iDpeQ2z1L80g4USPzdUPxDDIm0m/eyKlBVZquF76UVvEc0EHiIZjbQa6SXQgzBj6yWm8eUuX4mmHGQEFUF/3X1nc7nXu8t9SwsfAsWk0JEpsQOSaVDmuFJ2G55GO/rgxp3G5szmX1wCQio8fSF04mhHrbuPAznRpHAtBNW6kFJDLbZ+5J3svwHfkS3PlR9Zfw2ko2ZT5LTNwxA/KS+aXEx7JcEwDaHR+0CBrHTI28SfoCyJnUFPnzN2shBTNkGE5gkx168ZAZDB4+mNI7PFR+/pzoa9dVe2zEcYh5N1AA3xF3Rh/beXrRGPRyDwQzGGs3jBMtxA6hXFsTeegzJwhJ6m0oJri5NII6a7/otWEQpx5EKVCN9YxFPwK7FbWuaNAYBPD20lMOYPVUNfwfdbERz2cIYatVW6joaoxiF9xvns13ZJMBk1b3byDKhZZ+8z7qUXCRtx+GZ+b/1462PoUt1BZX7oz6+8miC9CDF+iqixXQ2XcSRbqT7Oy5IkUXAPk1VEmXWh/7sinG2ohj79iwRFfqYWKXHThJO/T4qIBfUUgdsHuakuFNYM5EyZe6P9t1vQ+UrmGCkOiIdpklTEycG3ndHT9H+0wRoR547O3ilteVteuSVDdMR/XvyPZamIPZV6MbC4vgpodFO/1vdenTsIPQV/wqwwMkzoSe7wQZg1A81bFD4CeMgJmO8ZFfIBUczMLEw0s3kvg4o7vJ5yXMzVKjEob9V+D6w24kALruHy+EkilsOInqvYc2VJMy8XxMTUkCrCpkTamtVGcRBcHUn4KCPgoF3KFVJqOfNCFfnlq3JB+bwZ/cp1aF9JKvSotr6HEXGVkBILG7KDt3U3FEBu/+bYDi+kPP1/AgO8x28ZSVlESwaLORcv6Edt3t4lpQHvM9/+CV98I72ajisREmAb9MD0wITAJBgUrDgMCGgUABBRqgZ/wtxdW8d3M7waGVOjCkGjlQgQUGVtjR8gSWzJRRrxlbLNw5CafsKMCAgQA","password":"11","customFields":[]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

entries[]

Array

Key Store entry list

entries[].alias

String

Alias

entries[].clientCertId

Number

Client Certificate ID

entries[].md5

String

MD5 hash

entries[].sha1

String

SHA1 hash

entries[].message

String

Import operation status message. 'Imported successfully' - all is OK, 'Already exists' - key present in Key Vault, otherwise - error message

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 185
+
+{"entries":[{"alias":"admin@ccmqa.com","clientCertId":141,"md5":"5f646a050e14d92b60c376128a79e691","sha1":"e99ed5c3bff4fd1dda576ee1dd2cd962e521d6e5","message":"Imported successfully"}]}
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/{personId}/import-key
ParameterDescription

personId

Person ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

p12

String

Base64 encoded pkcs12 file

[Must not be empty]

password

String

Password to access pkcs12 file

Optional

customFields

Array

An array of custom fields if required

Optional

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/163/import-key' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21566' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"p12":"MIIc9AIBAzCCHK4GCSqGSIb3DQEHAaCCHJ8EghybMIIclzCCBXwGCSqGSIb3DQEHAaCCBW0EggVpMIIFZTCCBWEGCyqGSIb3DQEMCgECoIIE+jCCBPYwKAYKKoZIhvcNAQwBAzAaBBRkrpqy0Rl09IE89cMzT+8i0+lhOAICBAAEggTIXoY6WMPXG7P4x888tra7Y49A4GYbv5szwUKjjddvux14IPB8yz0MPeAD4TO/5Qmp4ERF3V/TF6YBL5MxQw+IEHDF3r1P3drvdd/Ku4R/us6XSHfphqGHT9BVmP+qtZOLOkhe3r7NNLVETNw6GZNQPKRKMf6VbLJE9VpJO4evI23wSZxqUnfKZpkGYtoh+jIBLxV31erwxa4/ffBeVlFYPw+MNj38lMn7Q3Xr5vys6PmLBtUgRTnbER/jXxbo9vXP6pJobupZpwfQRabzqm3Gj7qk51NNAfj8I7hXG2u8VcCAB+LJuj6CqGf13zhkEcibjI+JlqHKI7FfzHFZFLNURrRciGpd6WxT4R27GTPUqiNwmK5XU+GTwgO/NNXQCQTFKJ3HZ1LJj4i3hbUBBAzABTD7OB7Zns6vdSzHx447Qc9hY2g907ZhluLhyAxKNSkZXrRArJKadDNYV+eD9zdY80/itKQGKqR0haFkZW1NMEs2ZQsWAPgMcvdyxkU47+QvGH7ETBnpWGJFVRH/x4juLo46y8IQ9/umiyxYmJ9q9TEy7wm/Fg4UqG9JXckXNN5Apsk4Y2Me7I+uPXFeHbmifzgngMRvrCb+2NppOaPrvCPFCbknVq3091dLHDd2Ajd0vTtP/467YI0xPyr+Yzx6RcFm7oFNtx5Z8JRKpJT4RFF6ZVMkMsKAozsAHJsbtCB9JBE7gRJzm6HPEVSqwZ+49CtIyJ5JTuzDV/DB0DDg39y+27NpAL/Gj4Em4wcEhdyGpnsAhMO+FNMLRDPQGDbdOhdrz3eKIVy3wqxIiJb6VEOuV+J8cLxF7rvqctj+tGQP5VVxsXSHJHQCFPeo5GHlBk/GqG/ZIbxqJdYag+Bpyf7C/XKd85VriiBO949Jio4HxDe/C62j/RwqbTeUoJ7FU/0JPsGhxkloPbmLNmoXv9aJlewwjYDgqSsHfjQpVGNopcRiX0X1HPZNMlF4XpZ8lEGK+RAbYJnHhp/RQKe80tKg4NY7WYmB9cHYhvax8a0VMuKmYlzpugHJRQlE0q+i3Gzh8nPeEjN4HX+RrwXBNbHDBtuUYdNBh6vSvdD64w1Jw22zF8RsfN5vRCDsBM64bwdWlUW7LYhV6eiqrle8X6JIEUUl2OIQLwUCL6m0LzUwzUh902+iEAZi28QnNSQB0bVoxfnCnN8P978+B5oVDhsbRjPhplSjD7BvSSBPiTpjesRFGIqPkzAMXlfbOszyXRwEErtwDNlqp/qj110hDxskuaV154HDcZLSyqJGvs/GxooBCNIDdxI75eATwnwMNHHxo+gebj9crLycA1AkHRr3/iFHbDZN0Hd2kIm7Z+beD7DmBCLFY8AcfeQBYmCxo4BLHVBIvr9hlqUxi1zU4KEWFhHgo8/S4qOXfR99c7LvfV3rOaE4qEyj7cxJean1smnEp9uc0chUXGbL+MsgrkAXOfafGNkxmAflwEh/WyhtsVjU9saDvWzRN3sJnkwlhuqBfqGfV0402TmHYpaGzyOeHqn7Wir/Nn7F5P0BmgnSmJIIG0bKE44hTJcvppcEju+qmyJUCM9NmahMSmwkZLTWAx9mhZDe2OqC6d4yqIRK9I/gHwMLqhlFuSOzwhDnpb+qwVY3QMw+MVQwIwYJKoZIhvcNAQkVMRYEFI3YZBRdwYCDyiA9uLphQZnGCtx2MC0GCSqGSIb3DQEJFDEgHh4AYQBkAG0AaQBuAEAAYwBjAG0AcQBhAC4AYwBvAG0wghcTBgkqhkiG9w0BBwagghcEMIIXAAIBADCCFvkGCSqGSIb3DQEHATAoBgoqhkiG9w0BDAEGMBoEFA6laLzuLYF2mkOyxGvWfC04PwIOAgIEAICCFsCgCj9qK1Vzx9McX8htHPTeg2LiplMfbMQhCGotrhNAq06NFlKSwIjkLnLijveF3oosyZ4mTYuNBy4Wqg9Q7uZpne5hWTKD87X4NUn1cSB3Xq8ATRTA6pVAF6uZCDQwLBtmUBaRCsIPRNjukLqAxvyQavSqAHmn1+v3Na0BIc8x4RRN6RxiJnMiHEAhwQecx8WT802xGMyXvga06N3fXYGr0w0sVMHckZm0yagJObQ8AMQci9YdiFJsUtfrL+SGkfWgG0SyG3PP77ZFALVciwtMs82Y+yPDC6ZJVsas15UqAzbWGtWyqy459fVpIUu0LNo4Mqg2UeG3toZTcBYF1SfnYalbRsPSN3miL9NQJmluTWv0l/jm3YZETDpeRsbgpm2wuDvkBGxzzS8mwlmwenjKXfPD8uGpbyLX7oxP0m0a+zrQvkApbNI2ZI7Ebgo/JjNOhr9JWXo5hEjOgNh+dRv+gqwKgNy0bxEbncHkQc/xxMpDGfyUpHNEFvZLWdMwrz+l1Xy+3lI8jHsyZ3uMj8e93ADQnWuMSPhGwihFqbTU0HwIGiQt0DgNK87jFxlc+/iZ5QEh6T62jTR7jXY+sVQ1PfTBWQ0UwGYhF1VavFpPzNa/UmTppo8mV8eGNfChcUn0nk1O5jQQOV7rx5uSmKFKgGUP2upTKkikIePrhjqIMXzFgalmMQ/loBimxi/5fEMlZIVb9YAx5cBNVtx6ZdwsJ4J72WiAuLYkIialoVfCeLHr3v5Sk1oZbwT/mFxv85rNFGobD3LpSU87iJPghAQInKJyWHgaoRzyTubHqgnKJRrMFEb45FJ/EtTP50XCknQVHW7u/geDMNhAmCCA4KSBuhmWDSs6DnmXiDHaG/Msd4E1o/0X56fbRI+qFr+iaMSWIoXrps/SmuUQC8QTLs9qJ1mESXCLPyhsY9dZRMhtX+7qBRPElC+IKHsVTdmYS4cpANy+adviTipJMlwWvNJm7cgRrOcRdFD7xOsxRX1cICCoEsaRKifzzts6xfOGJRE/1KFi+krlH3zQuVkooky/PWQXjgRKdRJvIUIX3RQNCwmDHeAA9IhmmlXARjJOtRMj/eHOOS93y0dYrsA5Md5p5NTX5FLQHWXF/rSvCD841345T7gF4c0zYYKj9toQ57qExx/TZvdrIQcNPoD80ZQk4YSd9O54f7KxD5uTOPjAmuzvFrrrb6y6Zxh7jU37x0KHJmiwPSa7fYCwzR9zuWwfFXJ+z0ztWWbKE39ZeVWPkM1Dx6il+Pew99ftslUzoglfeU+OMcdd+pQkX2MiTHzGC7gt8krSQqt79HqmgD8iptVc7mW+m3JsyI3xT4hKTssqEZKYy9+t6UTNxSus1iaj1jKo3wieI8odgKzVhEyKxr54qVPDsmlbI+z4HY5/lnmkwV/OIyuVfr76+3EMQ+PhPJcb9z4zHkYkMDbeu5i1vsWvYyg92RfbYSaLbdNDxHnZAjb+bExDnwksariQk5r0C75hvveu2v7+T9meF2EbOPod1lVPJNN7SU0TiptIIfyBFTheha8gwIRUoaMPwfnLiYc/XdDNCEkcoRwUxYb4Cdgxf1kcEzuBJy7dERlKyPibTT9xzoHrQpMm3KgcPIvFXj3fDABcDw23mC16ZEfs/a17N2cfsH+UXHvNiphM/VJIWCHORj1o6gqs6lfV7S5NDEjwNgS1q8zRZF8RGrtbSjlAdyFJ3LlHDAvOAvBsN+OQRR7AB+mJvP+JxDrihDAx9Kggz7qBcTzsyzp7de5eka7ju/D73NBNnalKbvaBMmp5hkDMVvAZGLsgRGK4gEwtAtf5tBb/bQKFtvbwdHs63vh0V/fpRU4v2JWegl8mgexw+vNhRv9Sv93Zpw6PUSMYRYiTF/csOk3aemdUwCBEVyoElOvL1CJX2pKYchYzbKVk+00zLaAWlOhlsBCeVmVnZhi6HirFcUPWmzJS1AEa66feuy6nuJREcUbMLaLpIvjmd44T7oTqzZPFYNIi/9jCtXREp1Lav4z17CUAtGEmaRSwMjoorBjTLGgPF3/+/04MClWf3h4oKLyhtj98ric9r5KDhZRDnYZHCUxBXbkvAo55svvmKopCuB2coB2B8H44DOfc/3wKNk/ud9MzcyD/J9C8pBLGGdjwm70g8DYyoJCBOEuMff1879kQWJblNcIJJAlKf70UfOHpwc4Nw+MD9e66TR3LWV74SqUqSRvtGrtWRGernQnPRoEe1/DlaxlUxDESIyL9FzrcXROQRXCuufspczS2cUucWCESbJAUwVVShCTgRKv3HhTakkbw4U5dy89kLx9VWX/Qj0NPJYOaelef7EI+PLeYqxhwHNDbicXih4dE8L9ImsyzybV4tpO9cBxTQVYJkAPo2DWGB8UFjvbZBq8hxOeQ/GRx+bSKn7nm21c4t6DDH3Sp+jSNqi3851StlLP/TtspQDk8fq9/+WgcAEGlRCloW+8M/mAfh6ZYTRNJoqN3Ey4WkRMzPc6ZTCBzcqagAizj3CZreLoYPBCKdwv01BqqJM5q+FbfVzk5k8AqWDlotcNW0O4q4vl8mk8AmHDP5J/zy8Co5S2vfqD65vZsGdbOSjES1u6WMyltSnrIxjXdVzo3xriFt33aNc/wW3d12ZGoD0dHO6fJJw1QSWlVJqmZVWGQBjouz3o15V9f3GVJu812P1R4BKQCqz8M288LrD9gOTUrlUR+kXHg0Q7tHDqLTkGHZ2wV4gJZ8PQzoXn4tthqH8fbkHFIXDUyLAg6CrGxaJX9KCRzJ7WeLpTmJf/ljXbwySpI/zkFvK9EJT0tmEfsxUXnzzJLpnmlr3f/gkXn9TYkzB9S3V1yIvsk2IaDh0thZC2RNnbT1A9i4OvNTnAL8JnTkW3t2GB7BLU5bseHUnsdec2fitddaCPcOWmnPO33KoJ7bDRJun1l7zjJP5ZntShAdEJRUHOaAyTaY2Jm4PPm7hrgcVdltNT+4PiMkv9smqNrbovOhmGyYETyS9CxPqaS1iLn3RLkp6HiQTi5xekJXmyZl5ya/DhC3I7kZycV9ca3qEqdvbwF7PMG7Z48kPpTX8PS7gRP83ASjCqTLQROLkHl20+6VgM2+5kPiNA28OFOXrpTWdVnkMH6rHOSxnxMjejeoZEv+5vtvUH4owL5B82FH/fJ9QeDSo6iM+V2v9Xc8nkxl/3HWuRdJWCJ730J49kOheyXpEA9wt9aw5YpPhqJeBPa84kI9JtP5Tlkr3gGAtD/L+jO2Y+jbedQxCffc5R4OVBCndPMFLS+3awrCOP1WNiDQO7+CohGUssFxiRBIBJ948Fx1D7M8ZE8qKliDz+q7EcT5md7nR1d4exUn4aILmwbcwXGKvSiWTJmBGfH7iwSdMbr/ZtCiSfCYMref8ZHG5uO/tGQ/cpCZn67KfsWW6mC35UGnpxnohyyd95rOUSzHkAqi4PJx5tu1LGNXosy4VOSQeQ6ChExKkx2u1j55whlZqaFAsuWA4CxQo1mcny9Qjt8IAFjE2YVbvtvLhMn/lcH3DQUukA6LJPB59udh0lgZDSuQSwRb35+9Q8jWdiCUUbWYJUR5TIwvSngtVt4g2P0eHncD0luHz21F9txsmrql6IOnr5YxU4KptQnU0SssvuYb5jfUO3oOBvvkqCM1vntzgDSKvS53hn0RdH+wY68gltoHsJDFjDVXmobhcHr5ubX3PK11r2uGbDOWApc/h+Bmkwf5rsVn8fCHbnWe+1wQTPSfyujpcC7PffJ/Knmv+vYLAWofMC4TbIY451HIJ4xUHlZfHnaGnnJGf6Hlnpn2P6cFI4AXFNGAzxfAjoNzQowuUQzKxtsEB4mng7hCEzKi5SdEcgTudd6qcMd9Kj1UJFED3gqu7Fo1tjM2EMWlinYOxQxlRSE1lpcd8Y8ZPljOUplZ3P0cSikSLyuGDVkXN94OagUMTNieF+oINFCZsU1aAqf/SxOMh7+tDUNvGj2VTIKa+kBlDTzl51aIGXGwCjj4d7HBJy4cbKH7nW4E2Q6xSKZLYf/UoF6jWao6lO5cpvWFENzGiI6o2fYEYfp2KVyRW+4liMKYT1g5na1NP4Z8VsfEKS6UNzOiiqoMcsiHz2L7qTtvDEL49wYVwuBNm8GHXQ32oZGexIDZz+uhO+nYfVJRRkNh2sKurLgA+NF7jAvP87nejqzwW+aI+SuSppnKe+QBvEfq2IeVaqdpau8qzdlmC3ke3vGC679m+9krN1YNmRdJAxEgs4WF2g1qjKG5hQKVA5uve5dQfFDbHv7y7jkd4zob32A2A1p37qjWESZoRYRtZVjuWduJXB8dG+2tqp8MonINGGbXNLfvahOs+RyiW12c0/17T8x72BSoXOK4DQuABOci0kS7OwjSpKD3joh/nn+Mg6Lmm6Luj+D8i8SB/+kv5+U9oWgbfKNKkz6ilY28px+D8H9P6wLwWFcsiSyO6Sb1vFMY0Wegdt5uXCupf4CVX7d9NEtSYpFKWP8Ufdc6zRvc5LofRJ8noxSpVou0I2+KTFUCfdhIA7LV62JmhC2k61QhN8YllYJcItQc5bgxrSYs/i7dVhwqPDUzbUAcO4q4xuQNtc4asozmjxb2YdidBtE4V2CMf7p//yTA9PGBqDbuv6Yx7RwavTdJW3bLBb+seQKrnYp8zV4u07DaOSOaEVUJfn9fTFt5QiCwOuo5Z2tr7hbn5rwvAA9pm6Br4lys5B5nMFetMp7jKByfZPjF8i1586IjWqgT3B+b7Jrp7qUs/FFmLA5jziVyeVzzGCiw/oXEI1g59Vn8hNPKY3CDXi5vsWVR6zQieA8wM1vXhXM4JdYdsU1fAwDqLf8s+XZND4zveACTdl836QIidvwpUQAkl2AoitI0lE5CNsDClqtY9KIf9TmTkwaWCPXtbQ3A+N/X6abreQn6Tv8w4cu7cu5+v2ebkAIomd9X/BtntSRUreLpZr1+yDOtu6+FNMX2d8c8lSjdO5CekVNXBXaJeyF47oKBmO5oOP3jfvHH7QqW+qXxFcor5x1SJI73eLv+9//z109sWnZ/Fc6aKi1eBe+/SSCisJs8Dh4/W2oLPxhfcMC6hhwvV6yB7dvKZ2eNYeuqR58JS9QwMD4DT3+Qq6Lu7CUcdUkgIQ2/SvnAOaPpRbC1VVoc+fZ/UuBA2DPafWPm0OZzoUA9wrSN5CBCcJLKvY0J2yW9FPuE2wy6CgXtN869K6sEQiHtXqd7hhqVEvmvykjmFFHX2THCEiDd0Jr/Upc7b/tM4tcrEe67AWa7qLCidhQx+lqviyuNgVLDKk73MlwcpFRyrFbZk34qf8H2y5A5DMXfUWr7/5mP4NMbb0b3CTsBWJfB5mu23EBJGifpv5iYGUaDh+n29lvv6X5cyDSJIEpNpDSdQliPaf0einf7EtlkIwVh1JPvxYmL2Xt2w0LXm5SP62zPYfGMYEY5lYW4c5qFSIzKeFjEU+dDA+9tIgtw5XAlkJFIQ2DBl1hIfJczbWJlj5lWX/jDsXk9gdJ13/kU3fRzmdtRhFWPuKWNHI6RJtmKq+6eUldgb7dPbLF8+nVALbSk47+DwqJs6AqKJr/jndJKHtfAdoob/1796/aQUdVHx7Qfzku//gsUEWEvOlUPGloOlBRwf6scvXtcsaGftIc52v6DmHh6A5ehmgdSFpZWoSmQ3BhfbEa2j3grUT9iuv54v4xMi8F1JDDu3tpQG8FwXg6fY2VvKjqHHf6hoS7Xtf5pFrggUbGbDc5gzx5QnPHPHnHuTdnAwcSVwPEh7/9oNe6zYCmhrrbOFEU3QKs7r3wsRe19yjLyyIAfLfrgFUjQ4eS9jNE/NCyDLecqZxg5As72j3uo9HjKnYM0iHC5S57+5IzGVUH7noqFJoyaVE/ATerqP0MqJ1ePaaKpbaE1dx822JWj2rQ0v0UtrsPwEiPMcfDQnxnuv2Norw0UFIm3tOHNQeD2XAcd/epyj43K1EWMc31IS7nPf6EitA0X+ziqFUyLzgqieRTXj9zmDdTzcSnYVdFOQJcMnJSlb9Q7FHfySyJlzGxGUe3ATalnq9psZ1V5ifnzmoAeLvRbdKWguOhPJDK6EemkJSYWvALkrOF+GJkabAhL2PzmOj6VUidgDLhjnwD5ZpmsC7gr8T+Nx1Vmu1ercVRuA66IClIfMijnoq4hjZLOMnvvVLop2yvVh3TMF6qOYQOg1v5Eoz9I0HFu20fn2UZHY2VThdnfCqRkvjYEROIPBRHJVhtPu5ypjS5RWxbVcn90YcBuqVKHDeFgfFPGq7x5fDdAaUNRZW5UZxLR4l9tk8wAAD/oVfoiuPpOXyD2kxqqbnn+UI22Dy0qHjd1JE+w0+WvNb263nTZAjAaM0qB538DHSd2lbsAKHF30C8lBWlsbAfxc8e9t0cqMiZ6R/fVJSwZJVQ507Z/lRVqpgTEFtSLysgBJw1NvUrhQPA1ISu89oEKiwHZDmkWpul7BgY+wYtRuZQBxb7Ji2Ny0y0j+SSBPCDmNZPV+i1Rt0l8YUbu7BH/mGjSMByIaNok4tEEh0pz79G+yZkUeMMUjPWTuiccEg85Jgwh25t62JQu/SnLpPEBjif0dDr3M3sA4jjWX6YxUiGN+Wlry89aoBhIfJFFiNBMtlN42EyonjJfYydof6t/rGeJAlehmfjzMcBRmZEkSUQ6sIqxf04NR3m7ylKv8Wb66DTJaVP5WYHBjuxqQip8hP+gxLb7atHuzV1DFJaU5O/UQ0QDK4FFeNaj1MZRMlAaTh0HBb/DTcZtdH7rDfcX/gft2pbCLwoCetuOiVZGCs0yiyafmUfDsO1QUcJ7PXFO8RGWmN/VXoTb9LJpJLIVGyL361E7IO+iDpeQ2z1L80g4USPzdUPxDDIm0m/eyKlBVZquF76UVvEc0EHiIZjbQa6SXQgzBj6yWm8eUuX4mmHGQEFUF/3X1nc7nXu8t9SwsfAsWk0JEpsQOSaVDmuFJ2G55GO/rgxp3G5szmX1wCQio8fSF04mhHrbuPAznRpHAtBNW6kFJDLbZ+5J3svwHfkS3PlR9Zfw2ko2ZT5LTNwxA/KS+aXEx7JcEwDaHR+0CBrHTI28SfoCyJnUFPnzN2shBTNkGE5gkx168ZAZDB4+mNI7PFR+/pzoa9dVe2zEcYh5N1AA3xF3Rh/beXrRGPRyDwQzGGs3jBMtxA6hXFsTeegzJwhJ6m0oJri5NII6a7/otWEQpx5EKVCN9YxFPwK7FbWuaNAYBPD20lMOYPVUNfwfdbERz2cIYatVW6joaoxiF9xvns13ZJMBk1b3byDKhZZ+8z7qUXCRtx+GZ+b/1462PoUt1BZX7oz6+8miC9CDF+iqixXQ2XcSRbqT7Oy5IkUXAPk1VEmXWh/7sinG2ohj79iwRFfqYWKXHThJO/T4qIBfUUgdsHuakuFNYM5EyZe6P9t1vQ+UrmGCkOiIdpklTEycG3ndHT9H+0wRoR547O3ilteVteuSVDdMR/XvyPZamIPZV6MbC4vgpodFO/1vdenTsIPQV/wqwwMkzoSe7wQZg1A81bFD4CeMgJmO8ZFfIBUczMLEw0s3kvg4o7vJ5yXMzVKjEob9V+D6w24kALruHy+EkilsOInqvYc2VJMy8XxMTUkCrCpkTamtVGcRBcHUn4KCPgoF3KFVJqOfNCFfnlq3JB+bwZ/cp1aF9JKvSotr6HEXGVkBILG7KDt3U3FEBu/+bYDi+kPP1/AgO8x28ZSVlESwaLORcv6Edt3t4lpQHvM9/+CV98I72ajisREmAb9MD0wITAJBgUrDgMCGgUABBRqgZ/wtxdW8d3M7waGVOjCkGjlQgQUGVtjR8gSWzJRRrxlbLNw5CafsKMCAgQA","password":"11","customFields":[]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

ID of created certificate based on imported payload

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 10
+
+{"id":142}
+
+
+
+
+
+

Send enrollment invitation

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v2/{id}/invitation/send
ParameterDescription

id

Person ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

accountId

Number

Client Certificate Web Form Account ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v2/141/invitation/send' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21438' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json' \
+    -d '{"accountId":12}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 202 Accepted
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v1/{id}/invitation/send
ParameterDescription

id

Person ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

term

Number

Term for certificate in days

keyType

String

Allowed Key Type

profileId

Number

Profile ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v1/168/invitation/send' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21601' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json' \
+    -d '{"profileId":2342,"term":365,"keyType":"RSA - 2048"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 202 Accepted
+
+
+
+
+
+

List enrollment endpoints

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/person/v2/{id}/invitation/endpoint
ParameterDescription

id

Person ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v2/138/invitation/endpoint' -i -X GET \
+    -H 'login: admin_customer21417' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of Enrollment Form Endpoints

[].id

Number

Endpoint ID

[].name

String

Endpoint name

[].url

String

Endpoint url

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 117
+
+[{"id":1502,"name":"test SMIME_WEB_FORM21423","url":"https://cert-manager.com/customer/test/smime/${URI_EXTENSION}"}]
+
+
+
+
+
+

List enrollment endpoint accounts

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/person/v2/{id}/invitation/endpoint/{endpointId}/account
ParameterDescription

id

Person ID

endpointId

Client Certificate Enrollment Form Endpoint ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/person/v2/137/invitation/endpoint/1500/account' -i -X GET \
+    -H 'login: admin_customer21410' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of Enrollment Form Endpoint Accounts

[].id

Number

Account ID

[].name

String

Account name

[].profiles[]

Array

Array of profiles names

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 129
+
+[{"id":8,"name":"Client Cert Enrollment Form Account","profiles":["Client cert SASP -666981075","Client cert SASP -1254026162"]}]
+
+
+
+
+
+
+
+
+

Domains

+
+
+

View domains

+
+

List domains

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

name

Filter by name

state

Filter by state, possible values [active, inactive]

status

Filter by status, possible values [requested, approved]

orgId

Filter by organization ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1?size=10&position=0' -i -X GET \
+    -H 'login: admin_customer1440' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested domains

[].id

Number

Domain ID

[].name

String

Domain

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 4
+Content-Type: application/json
+Content-Length: 133
+
+[{"id":104,"name":"example0.com"},{"id":105,"name":"example1.com"},{"id":106,"name":"example2.com"},{"id":107,"name":"example3.com"}]
+
+
+
+
+
+

Count domains

+
+

Deprecated

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

name

Filter by name

state

Filter by state, possible values [active, inactive]

status

Filter by status, possible values [requested, approved]

orgId

Filter by organization ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/count?size=10&position=0' -i -X GET \
+    -H 'login: admin_customer1396' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

count

Number

Count for domains

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 11
+
+{"count":4}
+
+
+
+
+
+

Get domain details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}
ParameterDescription

id

Domain ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/113' -i -X GET \
+    -H 'login: admin_customer1458' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Domain ID

name

String

Domain name

delegationStatus

String

Domain delegation status. Available values are: [ACTIVE, REQUESTED]

state

String

Domain state. Available values are: [SUSPENDED, ACTIVE]

validationStatus

String

Domain validation status. This field is shown only if DCV is enabled for customer. Available values are: [Not validated, Validated, Expired]

validationMethod

String

Domain validation method. This field is shown only if DCV is enabled for customer. Available values are: [HTTP_CSR_HASH, CNAME_CSR_HASH, EMAIL, HTTPS_CSR_HASH, DNSTXT_RANDOM_VALUE]

dcvValidation

String

DCV validation date. This field is shown only if DCV is enabled for customer. Format: yyyy-MM-dd

dcvExpiration

String

DCV expiration date. This field is shown only if DCV is enabled for customer. Format: yyyy-MM-dd

ctLogMonitoring.enabled

Boolean

CT Log monitoring feature enable/disable

ctLogMonitoring.includeSubdomains

Boolean

Include subdomains

ctLogMonitoring.bucketId

String

Certificate Bucket ID for monitored certificates

ctLogMonitoring.enabled

Boolean

CT Log monitoring feature enable/disable

ctLogMonitoring.includeSubdomains

Boolean

Include subdomains

ctLogMonitoring.bucketId

String

Certificate Bucket ID for monitored certificates

delegations[]

Array

List of domain delegations, filtered by client admin credentials.

delegations[].orgId

Number

Organization id

delegations[].certTypes

Array

Certificate types. Available values are: [SSL, SMIME, CodeSign]

delegations[].domainCertificateRequestPrivileges

Array

Domain certificate request privileges. Available values are: [DOMAIN, SUBDOMAIN, WILDCARD_1ST_LEVEL, WILDCARD_2ND_LEVEL]

delegations[].status

String

Delegation status. Available values are: [ACTIVE, REQUESTED]

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 416
+
+{"id":113,"name":"ccmqa.com","delegationStatus":"ACTIVE","state":"ACTIVE","validationStatus":"VALIDATED","validationMethod":"EMAIL","dcvValidation":"2025-08-15","dcvExpiration":"2026-08-15","delegations":[{"orgId":849,"certTypes":["SSL"],"domainCertificateRequestPrivileges":["DOMAIN"],"status":"ACTIVE"}],"ctLogMonitoring":{"bucketId":"713d5d33-4c21-494a-9ab2-2675fe7aba4e","enabled":true,"includeSubdomains":true}}
+
+
+
+
+
+
+

Manage domains

+
+

Create domain

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Domain name

[Must not be null, Size must be between 4 and 255 inclusive]

description

String

Domain description (optional)

[Maximum length is 255 characters or can be empty]

active

Boolean

Required domain state

Set 'false' if you want to create domain in suspended state

ctLogMonitoring.enabled

Boolean

CT Log monitoring feature enable/disable

Set 'false' if you want to disable CT Log monitoring.

ctLogMonitoring.includeSubdomains

Boolean

Include subdomains

[]

ctLogMonitoring.bucketId

String

Certificate Bucket ID for monitored certificates. Required if CT Log monitoring is going to be enabled.

[]

delegations[]

Array

Domain delegations list

[Must not be null, Size must be between 1 and 2147483647 inclusive]

delegations[].orgId

Number

Organization ID

delegations[].certTypes

Array

Domain delegation certificate types

Allowed values: [SSL, SMIME, CodeSign]

delegations[].domainCertificateRequestPrivileges

Array

Domain delegation domain certificate request privileges

Allowed values: [DOMAIN, SUBDOMAIN, WILDCARD_1ST_LEVEL, WILDCARD_2ND_LEVEL]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1423' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"testdomain.com","description":"Domain created via REST API","active":true,"ctLogMonitoring":{"bucketId":"fdf23c27-59da-45b0-8b56-64b0f0841ea8","enabled":true,"includeSubdomains":true},"delegations":[{"orgId":826,"certTypes":["SSL"],"domainCertificateRequestPrivileges":["DOMAIN","SUBDOMAIN"]}]}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

Url location of created domain

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/domain/v1/100
+
+
+
+
+
+

Update/Enable/Disable Ct Log Monitoring for Domain

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/monitoring
ParameterDescription

id

Domain ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

enabled

Boolean

CT Log monitoring feature enable/disable

Set 'false' if you want to disable CT Log monitoring

includeSubdomains

Boolean

Include subdomains

[]

bucketId

String

Certificate Bucket ID for monitored certificates. Required if CT Log monitoring is going to be enabled.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/108/monitoring' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1443' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+  "enabled": true,
+  "includeSubdomains": true,
+  "bucketId": "50ad58f2-2c6e-46b0-b201-f4c05830322f"
+}
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete domain

+
+ + + + + +
+ + +Master Registration Authority Officers (MRAO) can delete any domain. Registration Authority Officers (RAO) and Department Registration Authority Officers (DRAO) can only delete domains if they have permission to manage all organizations that the domain has been assigned to. +
+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}
ParameterDescription

id

Domain ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/102' -i -X DELETE \
+    -H 'login: admin_customer1431' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Activate domain

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/activate
ParameterDescription

id

Domain ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/87/activate' -i -X PUT \
+    -H 'login: admin_customer1372' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Suspend domain

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/suspend
ParameterDescription

id

Domain ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/118/suspend' -i -X PUT \
+    -H 'login: admin_customer1482' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delegate domain

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/delegation
ParameterDescription

id

Domain ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

certTypes

Array

Certificate types

Allowed values: [SSL, SMIME, CodeSign]

domainCertificateRequestPrivileges

Array

Domain certificate request privileges

Allowed values: [DOMAIN, SUBDOMAIN, WILDCARD_1ST_LEVEL, WILDCARD_2ND_LEVEL]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/88/delegation' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1375' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"orgId":793,"certTypes":["SSL"],"domainCertificateRequestPrivileges":["DOMAIN","SUBDOMAIN"]}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delegate domains

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

certTypes

Array

Certificate types

Allowed values: [SSL, SMIME, CodeSign]

domainIds

Array

Domain IDs

[Must not be null, Size must be between 1 and 1000 inclusive]

domainCertificateRequestPrivileges

Array

Domain certificate request privileges

[Size must be between 1 and 2147483647 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/delegation' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1384' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"domainIds":[90,91],"orgId":800,"certTypes":["SSL","SMIME"],"domainCertificateRequestPrivileges":["DOMAIN","SUBDOMAIN"]}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Remove domain delegation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/delegation
ParameterDescription

id

Domain ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

certTypes

Array

Certificate types

Allowed values: [SSL, SMIME, CodeSign]

domainCertificateRequestPrivileges

Array

Domain certificate request privileges

Allowed values: [DOMAIN, SUBDOMAIN, WILDCARD_1ST_LEVEL, WILDCARD_2ND_LEVEL]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/116/delegation' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1473' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"orgId":860,"certTypes":["SSL"],"domainCertificateRequestPrivileges":["DOMAIN","SUBDOMAIN"]}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Approve delegation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/delegation/approve
ParameterDescription

id

Domain ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/92/delegation/approve' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1387' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"orgId":802}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Reject delegation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/domain/v1/{id}/delegation/reject
ParameterDescription

id

Domain ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

orgId

Number

Organization ID

[Must be at least 1, Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/domain/v1/114/delegation/reject' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1464' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"orgId":853}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+
+
+

Organizations

+
+
+ + + + + +
+ + +EV details and Organization Identifier are no longer supported by this API.
+EV details were moved to the EV SSL validation details.
+Organization Identifier was moved to the OV S/MIME validation details. +
+
+
+

View organizations

+
+

List organizations

+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1' -i -X GET \
+    -H 'login: admin_drao_customer21017' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21017'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested organizations

[].name

String

Organization name

[].id

Number

Organization ID

[].departments[]

Array

Departments array

[].departments[].id

Number

Department ID

[].departments[].name

String

Department name

[].departments[].parentName

String

Department’s parent organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 238
+
+[ {
+  "id" : 3018,
+  "name" : "org4Test",
+  "departments" : [ {
+    "id" : 3019,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  }, {
+    "id" : 3020,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  } ]
+} ]
+
+
+
+
+
+

List organizations by role

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v1/managedBy/{role}
ParameterDescription

role

Client admin’s requested role

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1/managedBy/DRAO_SSL' -i -X GET \
+    -H 'login: admin_rao_customer21052' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21052'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested organizations

[].id

Number

Organization ID

[].name

String

Organization name

[].parentName

String

Department’s parent organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 158
+
+[ {
+  "id" : 3034,
+  "name" : "department4Test",
+  "parentName" : "org4Test"
+}, {
+  "id" : 3035,
+  "name" : "department4Test",
+  "parentName" : "org4Test"
+} ]
+
+
+
+
+
+

List organizations by certificate type

+
+

Get organization list related to specific certificate type.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v1/report-type/{type}
ParameterDescription

type

Certificate type: SSL, Client, Device, CodeSign.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1/report-type/SSL' -i -X GET \
+    -H 'login: admin_rao_customer21024' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21024'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Array of requested organizations

[].id

Number

Organization ID

[].name

String

Organization name

[].departments[]

Array

Departments

[].departments[].id

Number

Department ID

[].departments[].name

String

Department name

[].departments[].parentName

String

Department’s parent organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 238
+
+[ {
+  "id" : 3021,
+  "name" : "org4Test",
+  "departments" : [ {
+    "id" : 3022,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  }, {
+    "id" : 3023,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  } ]
+} ]
+
+
+
+
+
+

Get organization details

+
+

Get organization details.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v1/{id}
ParameterDescription

id

ID of organization whose details are being requested

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1/3009' -i -X GET \
+    -H 'login: admin_rao_customer20996' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20996'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Organization name

id

Number

Organization ID

schacHomeOrganization

String

Organization SCHAC code. (Deprecated, please refer to 'alias' instead).

alias

String

Organization alias

secondaryName

String

Organization alternative name

contactEmails

String

Contact emails, separated by comma

contactWebhook

String

Contact webhook url

contactSlack

String

Contact Slack webhook url

contactTeams

String

Contact Teams webhook url

address1

String

Address details

address2

String

Address details

address3

String

Address details

city

String

City

stateOrProvince

String

State or province

postalCode

String

Postal code

country

String

Country

validationStatus

String

Validation status. Deprecated, please use 'Organization validations' API to view organization validations.

secondaryValidationStatus

String

Secondary validation status. Deprecated, please use 'Organization validations' API to view organization validations.

sslCertsApiEnabled

Boolean

Allow Web / REST API operations for SSL certificates of this organization / department.

clientCertsApiEnabled

Boolean

Allow Web / REST API operations for Client certificates of this organization / department.

clientCertificate.allowKeyRecoveryByMasterAdmins

Boolean

Allow key recovery by Master admins

clientCertificate.allowKeyRecoveryByOrgAdmins

Boolean

Allow key recovery by Org admins

clientCertificate.allowKeyRecoveryByDepartmentAdmins

Boolean

Allow key recovery by Department admins

certTypes[]

Array

Array of allowed certificate types

departments[]

Array

Departments array

departments[].id

Number

Department ID

departments[].name

String

Department name

departments[].parentName

String

Department’s parent organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 787
+
+{
+  "id" : 3009,
+  "name" : "org4Test",
+  "certTypes" : [ "SSL" ],
+  "departments" : [ {
+    "id" : 3010,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  }, {
+    "id" : 3011,
+    "parentName" : "org4Test",
+    "name" : "department4Test"
+  } ],
+  "contactEmails" : "aa@scm.com,bb@scm.com",
+  "contactWebhook" : "https://certmanager.com/webhook",
+  "address1" : "Deribasovskaya 1",
+  "address2" : "Street 2",
+  "address3" : "Street 3",
+  "city" : "Odesa",
+  "stateOrProvince" : "Odeska oblast",
+  "postalCode" : "65059",
+  "country" : "UA",
+  "clientCertificate" : {
+    "allowKeyRecoveryByMasterAdmins" : true,
+    "allowKeyRecoveryByOrgAdmins" : true,
+    "allowKeyRecoveryByDepartmentAdmins" : true
+  },
+  "sslCertsApiEnabled" : true,
+  "clientCertsApiEnabled" : true
+}
+
+
+
+
+
+
+

Manage organizations

+
+

Create organization

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Organization name

[Must not be empty, Maximum length is 128 characters or can be empty]

alternativeName

String

Organization/Department alternative name

[Maximum length is 1024 characters or can be empty]

schacHomeOrganization

String

Organization SCHAC code. (Deprecated, please use 'alias' instead).

[Maximum length is 1024 characters or can be empty]

alias

String

Organization alias

[Maximum length is 1024 characters or can be empty]

contactEmails

String

Contact emails, separated by comma

[Must be a valid CSV list of emails, Maximum length is 512 characters or can be empty]

contactWebhook

String

Contact webhook url

[Maximum length is 2048 characters or can be empty]

contactSlack

String

Contact Slack webhook url

[Maximum length is 2048 characters or can be empty]

contactTeams

String

Contact Teams webhook url

[Maximum length is 2048 characters or can be empty]

address1

String

Address 1

[Must not be empty, Maximum length is 128 characters or can be empty]

address2

String

Address 2

[Maximum length is 128 characters or can be empty]

address3

String

Address 3

[Maximum length is 128 characters or can be empty]

city

String

City

[Maximum length is 32 characters or can be empty, Either 'city' or 'stateProvince' must not be blank at least]

stateProvince

String

State or Province

[Maximum length is 32 characters or can be empty, Either 'city' or 'stateProvince' must not be blank at least]

postalCode

String

Postal Code

[Maximum length is 10 characters or can be empty]

clientCertificate

Object

Client certificate details

[Must not be null]

clientCertificate.allowKeyRecoveryByMasterAdmins

Boolean

Allow key recovery by Master admins

[]

clientCertificate.allowKeyRecoveryByOrgAdmins

Boolean

Allow key recovery by Org admins

[]

clientCertificate.allowKeyRecoveryByDepartmentAdmins

Boolean

Allow key recovery by Department admins

[]

country

String

Country

[Must not be empty, Size must be between 2 and 2 inclusive]

sslCertsApiEnabled

Boolean

Allow Web / REST API operations for SSL certificates of this organization.

[]

clientCertsApiEnabled

Boolean

Allow Web / REST API operations for Client certificates of this organization.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer20982' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20982' \
+    -d '{
+  "name" : "Organization",
+  "address1" : "First street, 123",
+  "address2" : "Block 2",
+  "address3" : "Office 34",
+  "city" : "Odesa",
+  "stateProvince" : "Odeska oblast",
+  "postalCode" : "65000",
+  "country" : "UA",
+  "clientCertificate" : {
+    "allowKeyRecoveryByMasterAdmins" : true,
+    "allowKeyRecoveryByOrgAdmins" : false,
+    "allowKeyRecoveryByDepartmentAdmins" : false
+  },
+  "sslCertsApiEnabled" : true,
+  "clientCertsApiEnabled" : true,
+  "contactEmails" : "bb123@cc,aa456@cc",
+  "contactWebhook" : "https://certmanager.com/webhook"
+}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created organization.

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/organization/v1/3003
+
+
+
+
+
+

Create department

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

parentOrgName

String

Parent organization name.

[Must not be empty, Maximum length is 128 characters or can be empty]

name

String

Department name

[Must not be empty, Maximum length is 128 characters or can be empty]

address1

String

Address 1

[Must not be empty, Maximum length is 128 characters or can be empty]

address2

String

Address 2

[Maximum length is 128 characters or can be empty]

address3

String

Address 3

[Maximum length is 128 characters or can be empty]

city

String

City

[Maximum length is 32 characters or can be empty, Either 'city' or 'stateProvince' must not be blank at least]

stateProvince

String

State or Province

[Maximum length is 32 characters or can be empty, Either 'city' or 'stateProvince' must not be blank at least]

postalCode

String

Postal Code

[Maximum length is 10 characters or can be empty]

clientCertificate

Object

Client certificate details

[Must not be null]

clientCertificate.allowKeyRecoveryByMasterAdmins

Boolean

Allow key recovery by Master admins

[]

clientCertificate.allowKeyRecoveryByOrgAdmins

Boolean

Allow key recovery by Org admins

[]

clientCertificate.allowKeyRecoveryByDepartmentAdmins

Boolean

Allow key recovery by Department admins

[]

country

String

Country

[Must not be empty, Size must be between 2 and 2 inclusive]

sslCertsApiEnabled

Boolean

Allow Web / REST API operations for SSL certificates of this department.

[]

clientCertsApiEnabled

Boolean

Allow Web / REST API operations for Client certificates of this department.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer20828' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20828' \
+    -d '{
+  "parentOrgName" : "org4Test",
+  "name" : "Department",
+  "address1" : "First street, 123",
+  "address2" : "Block 2",
+  "address3" : "Office 34",
+  "city" : "Odesa",
+  "stateProvince" : "Odeska oblast",
+  "postalCode" : "65000",
+  "country" : "UA",
+  "clientCertificate" : {
+    "allowKeyRecoveryByMasterAdmins" : true,
+    "allowKeyRecoveryByOrgAdmins" : false,
+    "allowKeyRecoveryByDepartmentAdmins" : true
+  },
+  "sslCertsApiEnabled" : true,
+  "clientCertsApiEnabled" : true
+}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created department

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/organization/v1/2928
+
+
+
+
+
+

Update organization or department

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v1/{id}
ParameterDescription

id

ID of organization whose details are being updated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Organization/Department name

[Maximum length is 128 characters or can be empty]

alternativeName

String

Organization/Department alternative name

[Maximum length is 1024 characters or can be empty]

schacHomeOrganization

String

Organization SCHAC code. (Deprecated, please use 'alias' instead).

[Maximum length is 1024 characters or can be empty]

alias

String

Organization alias

[Maximum length is 1024 characters or can be empty]

contactEmails

String

Contact emails, separated by comma

[Must be a valid CSV list of emails, Maximum length is 512 characters or can be empty]

contactWebhook

String

Contact webhook url

[Maximum length is 2048 characters or can be empty]

contactSlack

String

Contact Slack webhook url

[Maximum length is 2048 characters or can be empty]

contactTeams

String

Contact Teams webhook url

[Maximum length is 2048 characters or can be empty]

address1

String

Address 1

[Maximum length is 128 characters or can be empty]

address2

String

Address 2

[Maximum length is 128 characters or can be empty]

address3

String

Address 3

[Maximum length is 128 characters or can be empty]

city

String

City

[Maximum length is 32 characters or can be empty]

stateProvince

String

State or Province

[Maximum length is 32 characters or can be empty]

postalCode

String

Postal Code

[Maximum length is 10 characters or can be empty]

country

String

Country

[Size must be between 2 and 2 inclusive]

sslCertsApiEnabled

Boolean

Allow Web / REST API operations for SSL certificates of this department.

[]

clientCertsApiEnabled

Boolean

Allow Web / REST API operations for Client certificates of this department.

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1/3069' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21129' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst21129' \
+    -d '{
+  "name" : "My org",
+  "address1" : "First street, 123",
+  "address2" : "Block 2",
+  "address3" : "Office 34",
+  "city" : "Odesa",
+  "stateProvince" : "Odeska oblast",
+  "postalCode" : "65000",
+  "country" : "UA",
+  "alternativeName" : "My organization",
+  "contactEmails" : "aa22@cc.com,bb33@cc.com",
+  "sslCertsApiEnabled" : true,
+  "clientCertsApiEnabled" : true
+}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Organization name

secondaryName

String

Organization secondary name

schacHomeOrganization

String

Organization SCHAC code. (Deprecated, please use 'alias' instead).

alias

String

Organization alias

contactEmails

String

Contact emails, separated by comma

contactWebhook

String

Contact webhook url

contactSlack

String

Contact Slack webhook url

contactTeams

String

Contact Teams webhook url

id

Number

Organization ID

address1

String

Address details

address2

String

Address details

address3

String

Address details

city

String

City

stateOrProvince

String

State or province

postalCode

String

Postal code

country

String

Country

validationStatus

String

Validation status. Deprecated, please use 'Organization validations' API to view organization validations.

secondaryValidationStatus

String

Secondary validation status. Deprecated, please use 'Organization validations' API to view organization validations.

sslCertsApiEnabled

Boolean

Allow Web / REST API operations for SSL certificates of this organization / department.

clientCertsApiEnabled

Boolean

Allow Web / REST API operations for Client certificates of this organization / department.

clientCertificate.allowKeyRecoveryByMasterAdmins

Boolean

Allow key recovery by Master admins

clientCertificate.allowKeyRecoveryByOrgAdmins

Boolean

Allow key recovery by Org admins

clientCertificate.allowKeyRecoveryByDepartmentAdmins

Boolean

Allow key recovery by Department admins

certTypes[]

Array

Array of allowed certificate types

departments[]

Array

Departments array

departments[].id

Number

Department ID

departments[].name

String

Department name

departments[].parentName

String

Department’s parent organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 601
+
+{
+  "id" : 3069,
+  "name" : "My org",
+  "certTypes" : [ "SMIME", "CodeSign", "SSL" ],
+  "secondaryName" : "My organization",
+  "contactEmails" : "aa22@cc.com,bb33@cc.com",
+  "address1" : "First street, 123",
+  "address2" : "Block 2",
+  "address3" : "Office 34",
+  "city" : "Odesa",
+  "stateOrProvince" : "Odeska oblast",
+  "postalCode" : "65000",
+  "country" : "UA",
+  "clientCertificate" : {
+    "allowKeyRecoveryByMasterAdmins" : false,
+    "allowKeyRecoveryByOrgAdmins" : false,
+    "allowKeyRecoveryByDepartmentAdmins" : false
+  },
+  "sslCertsApiEnabled" : true,
+  "clientCertsApiEnabled" : true
+}
+
+
+
+
+
+

Delete organization or department

+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v1/3004' -i -X DELETE \
+    -H 'login: admin_customer20989' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20989'
+
+
+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v1/{id}
ParameterDescription

id

Organization or department ID

+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Organization validations

+
+

V1 - Deprecated

+
+
+

List organization validations

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations
ParameterDescription

orgId

Organization ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2891/validations' -i -X GET \
+    -H 'login: admin_customer20764' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

An array of available validations

[].id

Number

Entity ID

[].validationLevel

String

Validation level. Possible values: [OV_SSL, OV_SMIME, EV_SSL]

[].status

String

Validation status

[].backgroundStatus

String

Validation background status. Can be one of [PENDING, FAILED], successful background validation empties the field with 'status' field set to VALIDATED

[].submitted

String

Submitted date

[].expires

String

Expires date

[].alternative

Boolean

Is alternative

[].backendId

Number

Backend ID

[].backendType

String

Backend type

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 275
+
+[{"id":306,"validationLevel":"OV_SSL","status":"PENDING","alternative":false,"backendId":2135,"backendType":"SASP"},{"id":307,"validationLevel":"OV_SSL","status":"VALIDATED","expires":"2026-02-15T09:21:10.497Z","alternative":false,"backendId":2136,"backendType":"DIGI_CERT"}]
+
+
+
+
+
+

Get organization validation details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/{validationId}
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2889/validations/305' -i -X GET \
+    -H 'login: admin_customer20761' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Entity ID

validationLevel

String

Validation level. Possible values: [OV_SSL, OV_SMIME, EV_SSL]

status

String

Validation status

backgroundStatus

String

Validation background status. Can be one of [PENDING, FAILED], successful background validation empties the field with 'status' field set to VALIDATED

submitted

String

Submitted date

expires

String

Expires date

alternative

Boolean

Is alternative

backendId

Number

CA Backend ID

validator

Object

Validator

validator.id

Number

Validator ID

validator.name

String

Validator name

backendType

String

CA Backend type

settings

Object

Validation settings. Tracking information for the CA backends. Possible settings: [EXTERNAL_ORG_NAME, EXTERNAL_ORG_ID, LEGACY_TRACKING_ID, LEGACY_BACKGROUND_TRACKING_ID, TRACKING_ID, BACKGROUND_TRACKING_ID, LAST_ERR_MSG_FROM_CA]

organizationDetails

Object

Validated organization details. Available only for Sectigo CA backends

organizationDetails.generalDetails

Object

General organization details

organizationDetails.generalDetails.legalName

String

Organization legal name

organizationDetails.generalDetails.assumedName

String

Organization’s assumed/DBA name (doing business as). Available only for EV validations.

organizationDetails.generalDetails.address1

String

Address line 1

organizationDetails.generalDetails.address2

String

Address line 2

organizationDetails.generalDetails.address3

String

Address line 3

organizationDetails.generalDetails.city

String

City

organizationDetails.generalDetails.stateProvince

String

State or province

organizationDetails.generalDetails.postalCode

String

Postal code

organizationDetails.generalDetails.country

String

Country code (ISO 3166-1 alpha-2)

organizationDetails.organizationIdentifier

String

Organization identifier. Available only for OV S/MIME validation

organizationDetails.evDetails

Object

EV details. Available only for EV validations.

organizationDetails.evDetails.registrationAgency

Object

Registration agency

organizationDetails.evDetails.registrationAgency.dunAndBradstreetNumber

String

DUN and Bradstreet Number

organizationDetails.evDetails.registrationAgency.registrationNumber

String

Company Registration Number

organizationDetails.evDetails.registrationAgency.city

String

Jurisdiction of city or town

organizationDetails.evDetails.registrationAgency.state

String

Jurisdiction of State

organizationDetails.evDetails.registrationAgency.country

String

Jurisdiction of Country. (ISO 3166-1 alpha-2 country code)

organizationDetails.evDetails.registrationAgency.city

String

City

organizationDetails.evDetails.registrationAgency.dateOfIncorporation

String

Date of incorporation

organizationDetails.evDetails.registrationAgency.businessCategory

String

Business category. Possible values: [PrivateOrganization, GovernmentEntity, BusinessEntity, NonCommercialEntity]

organizationDetails.evDetails.contractSigner

Object

Contract signer

organizationDetails.evDetails.contractSigner.forename

String

Forename

organizationDetails.evDetails.contractSigner.surname

String

Surname

organizationDetails.evDetails.contractSigner.email

String

Email

organizationDetails.evDetails.contractSigner.phoneNumber

String

Phone Number

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 823
+
+{"id":305,"validationLevel":"EV_SSL","status":"VALIDATED","expires":"2026-02-15T09:21:10.284Z","alternative":false,"backendId":2134,"backendType":"SASP","settings":{"TRACKING_ID":"706814613"},"organizationDetails":{"generalDetails":{"legalName":"New org4Test","assumedName":"Assumed Name","address1":"Addr 1","address2":"Street 2","address3":"Street 3","city":"Odesa","stateProvince":"Odeska oblast","postalCode":"65059","country":"UA"},"evDetails":{"registrationAgency":{"dunAndBradstreetNumber":"123456789","registrationNumber":"54564564","city":"Jurisdiction Locality","state":"Jurisdiction State","country":"CA","dateOfIncorporation":"2020-01-01","businessCategory":"PrivateOrganization"},"contractSigner":{"forename":"Signer Forename","surname":"Signer Surname","email":"signer@ccmqa.com","phoneNumber":"123456789"}}}}
+
+
+
+
+
+

Submit organization validation

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/submit
ParameterDescription

orgId

Organization ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationDetails

Object

Organization details

[Must not be null]

organizationDetails.generalDetails

Object

General organization details. Required for all validation levels.

[Must not be null]

organizationDetails.evDetails

Object

EV details. Required for EV validations

[]

organizationDetails.organizationIdentifier

String

Organization identifier. Applicable only for OV S/MIME validations. Stands for the legal person identification based on one of the following identity type references allowed by ETSI 319 412-1 standard and Baseline Requirements: National Value Added Tax (VAT), National Trade Register (NTR), Global Legal Entity (LEI), International Organization (INT), Government Entity (GOV)

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.legalName

String

Organization legal name

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.generalDetails.assumedName

String

Organization’s assumed/DBA name (doing business as). Applicable only for EV validations.

[Maximum length is 256 characters or can be empty]

organizationDetails.generalDetails.address1

String

Address line 1

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.address2

String

Address line 2

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.address3

String

Address line 3

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.city

String

City

[Maximum length is 32 characters or can be empty]

organizationDetails.generalDetails.stateProvince

String

State or province

[Maximum length is 32 characters or can be empty]

organizationDetails.generalDetails.postalCode

String

Postal code

[Maximum length is 10 characters or can be empty]

organizationDetails.generalDetails.country

String

Country code (ISO 3166-1 alpha-2)

[Must not be empty, Size must be between 2 and 2 inclusive]

organizationDetails.evDetails.registrationAgency

Object

Registration agency

[]

organizationDetails.evDetails.contractSigner

Object

Contract signer

[]

organizationDetails.evDetails.registrationAgency.dunAndBradstreetNumber

String

DUN and Bradstreet Number

[Maximum length is 20 characters or can be empty]

organizationDetails.evDetails.registrationAgency.registrationNumber

String

Company Registration Number

[Maximum length is 256 characters or can be empty]

organizationDetails.evDetails.registrationAgency.city

String

Jurisdiction of city or town

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.state

String

Jurisdiction of State

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.country

String

Jurisdiction of Country. (ISO 3166-1 alpha-2 country code)

[Must not be empty, Size must be between 2 and 2 inclusive]

organizationDetails.evDetails.registrationAgency.city

String

City

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.dateOfIncorporation

String

Date of incorporation. Format: yyyy-MM-dd.

[Must be in the past]

organizationDetails.evDetails.registrationAgency.businessCategory

String

Business category. Allowed values: [PrivateOrganization, GovernmentEntity, BusinessEntity, NonCommercialEntity]

[]

organizationDetails.evDetails.contractSigner.forename

String

Forename

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.evDetails.contractSigner.surname

String

Surname

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.evDetails.contractSigner.email

String

Email

[Must not be empty, Maximum length is 255 characters or can be empty]

organizationDetails.evDetails.contractSigner.phoneNumber

String

Phone number

[Maximum length is 32 characters or can be empty]

alternative

Boolean

Validation set. Primary (alternative = false) or Secondary (alternative = true). Note: Secondary validation sets are available only for accounts with the corresponding feature enabled.

[]

overwriteIfExists

Boolean

This flag is required to manage the processing when validation with such configuration already exists. By default, overwriting the existing validations is not allowed.

[]

backendId

Number

CA Backend ID. In order to get a list of available CA backends, please use "CA Backends" API.

[Must not be null]

validationLevel

String

Validation level

[Must not be null, Allowed values: [OV_SSL, OV_SMIME, EV_SSL]]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2901/validations/submit' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20779' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+     "validationLevel": "EV_SSL",
+     "alternative": false,
+     "backendId": 2143,
+     "overwriteIfExists": false,
+     "organizationDetails": {
+         "generalDetails": {
+             "legalName": "Organization legal name",
+             "assumedName": "Organization assumed name",
+             "address1": "Address line 1",
+             "address2": "Address line 2",
+             "address3": "Address line 3",
+             "city": "Odesa",
+             "stateProvince": "Odeska oblast",
+             "postalCode": "65000",
+             "country": "UA"
+         },
+         "evDetails": {
+             "registrationAgency": {
+                 "dunAndBradstreetNumber": "87654321",
+                 "registrationNumber": "12345678910",
+                 "city": "Odesa",
+                 "state": "Odeska oblast",
+                 "country": "UA",
+                 "dateOfIncorporation": "2025-03-12",
+                 "businessCategory": "NonCommercialEntity"
+             },
+             "contractSigner": {
+                 "forename": "Contract signer forename",
+                 "surname": "Contract signer surname",
+                 "email": "signer@email.com",
+                 "phoneNumber": "+123456789"
+             }
+         }
+     }
+ }
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/organization/v2/2901/validations/312
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created validation

+
+
+
+

Re-submit organization validation

+
+

Resets and submit the validation with the details provided in the request.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/{validationId}/revalidate
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationDetails

Object

Organization details. When not provided, re-validation will be started with the existing details.

[]

organizationDetails.generalDetails

Object

General organization details. Required for all validation levels.

[Must not be null]

organizationDetails.organizationIdentifier

String

Organization identifier. Applicable only for OV S/MIME validations. Stands for the legal person identification based on one of the following identity type references allowed by ETSI 319 412-1 standard and Baseline Requirements: National Value Added Tax (VAT), National Trade Register (NTR), Global Legal Entity (LEI), International Organization (INT), Government Entity (GOV)

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails

Object

EV details. Required for EV validations

[]

organizationDetails.generalDetails.legalName

String

Organization legal name

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.generalDetails.assumedName

String

Organization’s assumed/DBA name (doing business as). Applicable only for EV validations.

[Maximum length is 256 characters or can be empty]

organizationDetails.generalDetails.address1

String

Address line 1

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.address2

String

Address line 2

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.address3

String

Address line 3

[Maximum length is 128 characters or can be empty]

organizationDetails.generalDetails.city

String

City

[Maximum length is 32 characters or can be empty]

organizationDetails.generalDetails.stateProvince

String

State or province

[Maximum length is 32 characters or can be empty]

organizationDetails.generalDetails.postalCode

String

Postal code

[Maximum length is 10 characters or can be empty]

organizationDetails.generalDetails.country

String

Country code (ISO 3166-1 alpha-2)

[Must not be empty, Size must be between 2 and 2 inclusive]

organizationDetails.evDetails.registrationAgency

Object

Registration agency

[]

organizationDetails.evDetails.contractSigner

Object

Contract signer

[]

organizationDetails.evDetails.registrationAgency.dunAndBradstreetNumber

String

DUN and Bradstreet Number

[Maximum length is 20 characters or can be empty]

organizationDetails.evDetails.registrationAgency.registrationNumber

String

Company Registration Number

[Maximum length is 256 characters or can be empty]

organizationDetails.evDetails.registrationAgency.city

String

Jurisdiction of city or town

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.state

String

Jurisdiction of State

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.country

String

Jurisdiction of Country. (ISO 3166-1 alpha-2 country code)

[Must not be empty, Size must be between 2 and 2 inclusive]

organizationDetails.evDetails.registrationAgency.city

String

City

[Maximum length is 128 characters or can be empty]

organizationDetails.evDetails.registrationAgency.dateOfIncorporation

String

Date of incorporation. Format: yyyy-MM-dd.

[Must be in the past]

organizationDetails.evDetails.registrationAgency.businessCategory

String

Business category. Allowed values: [PrivateOrganization, GovernmentEntity, BusinessEntity, NonCommercialEntity]

[]

organizationDetails.evDetails.contractSigner.forename

String

Forename

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.evDetails.contractSigner.surname

String

Surname

[Must not be empty, Maximum length is 64 characters or can be empty]

organizationDetails.evDetails.contractSigner.email

String

Email

[Must not be empty, Maximum length is 255 characters or can be empty]

organizationDetails.evDetails.contractSigner.phoneNumber

String

Phone number

[Maximum length is 32 characters or can be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2897/validations/310/revalidate' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20773' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+     "organizationDetails": {
+         "generalDetails": {
+             "legalName": "Organization legal name",
+             "address1": "Address line 1",
+             "address2": "Address line 2",
+             "address3": "Address line 3",
+             "city": "Odesa",
+             "stateProvince": "Odeska oblast",
+             "postalCode": "65000",
+             "country": "UA"
+         },
+         "organizationIdentifier": "NTRBE-0876866142"
+     }
+ }
+'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Entity ID

validationLevel

String

Validation level. Possible values: [OV_SSL, OV_SMIME, EV_SSL]

status

String

Validation status

backgroundStatus

String

Validation background status. Can be one of [PENDING, FAILED], successful background validation empties the field with 'status' field set to VALIDATED

submitted

String

Submitted date

expires

String

Expires date

alternative

Boolean

Is alternative

backendId

Number

CA Backend ID

validator

Object

Validator

validator.id

Number

Validator ID

validator.name

String

Validator name

backendType

String

CA Backend type

settings

Object

Validation settings. Tracking information for the CA backends. Possible settings: [EXTERNAL_ORG_NAME, EXTERNAL_ORG_ID, LEGACY_TRACKING_ID, LEGACY_BACKGROUND_TRACKING_ID, TRACKING_ID, BACKGROUND_TRACKING_ID, LAST_ERR_MSG_FROM_CA]

organizationDetails

Object

Validated organization details. Available only for Sectigo CA backends

organizationDetails.generalDetails

Object

General organization details

organizationDetails.generalDetails.legalName

String

Organization legal name

organizationDetails.generalDetails.assumedName

String

Organization’s assumed/DBA name (doing business as). Available only for EV validations.

organizationDetails.generalDetails.address1

String

Address line 1

organizationDetails.generalDetails.address2

String

Address line 2

organizationDetails.generalDetails.address3

String

Address line 3

organizationDetails.generalDetails.city

String

City

organizationDetails.generalDetails.stateProvince

String

State or province

organizationDetails.generalDetails.postalCode

String

Postal code

organizationDetails.generalDetails.country

String

Country code (ISO 3166-1 alpha-2)

organizationDetails.organizationIdentifier

String

Organization identifier. Available only for OV S/MIME validation

organizationDetails.evDetails

Object

EV details. Available only for EV validations.

organizationDetails.evDetails.registrationAgency

Object

Registration agency

organizationDetails.evDetails.registrationAgency.dunAndBradstreetNumber

String

DUN and Bradstreet Number

organizationDetails.evDetails.registrationAgency.registrationNumber

String

Company Registration Number

organizationDetails.evDetails.registrationAgency.city

String

Jurisdiction of city or town

organizationDetails.evDetails.registrationAgency.state

String

Jurisdiction of State

organizationDetails.evDetails.registrationAgency.country

String

Jurisdiction of Country. (ISO 3166-1 alpha-2 country code)

organizationDetails.evDetails.registrationAgency.city

String

City

organizationDetails.evDetails.registrationAgency.dateOfIncorporation

String

Date of incorporation

organizationDetails.evDetails.registrationAgency.businessCategory

String

Business category. Possible values: [PrivateOrganization, GovernmentEntity, BusinessEntity, NonCommercialEntity]

organizationDetails.evDetails.contractSigner

Object

Contract signer

organizationDetails.evDetails.contractSigner.forename

String

Forename

organizationDetails.evDetails.contractSigner.surname

String

Surname

organizationDetails.evDetails.contractSigner.email

String

Email

organizationDetails.evDetails.contractSigner.phoneNumber

String

Phone Number

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 573
+
+{"id":310,"validationLevel":"OV_SMIME","status":"PENDING","expires":"2026-02-15T09:21:11.020Z","alternative":false,"backendId":2140,"backendType":"SASP","settings":{"TRACKING_ID":"12345678"},"validator":{"id":3206,"name":"client-admin-20774 client-admin-20774"},"organizationDetails":{"generalDetails":{"legalName":"Organization legal name","assumedName":null,"address1":"Address line 1","address2":"Address line 2","address3":"Address line 3","city":"Odesa","stateProvince":"Odeska oblast","postalCode":"65000","country":"UA"},"organizationIdentifier":"NTRBE-0876866142"}}
+
+
+
+
+
+

Change validator

+
+

Updates organization validation admin according to the provided request

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/{validationId}/validator
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

adminId

Number

Validator admin ID

[Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2885/validations/303/validator' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20753' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+    "adminId": 3194
+}
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 202 Accepted
+
+
+
+
+
+

Reset organization validation

+
+

Resets and removes organization validation.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/{validationId}
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2895/validations/309' -i -X DELETE \
+    -H 'login: admin_customer20770' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Synchronize organization validation

+
+

Synchronizes the organization validation with the CA backend.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/{validationId}/sync
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2907/validations/314/sync' -i -X POST \
+    -H 'login: admin_customer20788' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Entity ID

validationLevel

String

Validation level. Possible values: [OV_SSL, OV_SMIME, EV_SSL]

status

String

Validation status

backgroundStatus

String

Validation background status. Can be one of [PENDING, FAILED], successful background validation empties the field with 'status' field set to VALIDATED

submitted

String

Submitted date

expires

String

Expires date

alternative

Boolean

Is alternative

backendId

Number

CA Backend ID

validator

Object

Validator

validator.id

Number

Validator ID

validator.name

String

Validator name

backendType

String

CA Backend type

settings

Object

Validation settings. Tracking information for the CA backends. Possible settings: [EXTERNAL_ORG_NAME, EXTERNAL_ORG_ID, LEGACY_TRACKING_ID, LEGACY_BACKGROUND_TRACKING_ID, TRACKING_ID, BACKGROUND_TRACKING_ID, LAST_ERR_MSG_FROM_CA]

organizationDetails

Object

Validated organization details. Available only for Sectigo CA backends

organizationDetails.generalDetails

Object

General organization details

organizationDetails.generalDetails.legalName

String

Organization legal name

organizationDetails.generalDetails.assumedName

String

Organization’s assumed/DBA name (doing business as). Available only for EV validations.

organizationDetails.generalDetails.address1

String

Address line 1

organizationDetails.generalDetails.address2

String

Address line 2

organizationDetails.generalDetails.address3

String

Address line 3

organizationDetails.generalDetails.city

String

City

organizationDetails.generalDetails.stateProvince

String

State or province

organizationDetails.generalDetails.postalCode

String

Postal code

organizationDetails.generalDetails.country

String

Country code (ISO 3166-1 alpha-2)

organizationDetails.organizationIdentifier

String

Organization identifier. Available only for OV S/MIME validation

organizationDetails.evDetails

Object

EV details. Available only for EV validations.

organizationDetails.evDetails.registrationAgency

Object

Registration agency

organizationDetails.evDetails.registrationAgency.dunAndBradstreetNumber

String

DUN and Bradstreet Number

organizationDetails.evDetails.registrationAgency.registrationNumber

String

Company Registration Number

organizationDetails.evDetails.registrationAgency.city

String

Jurisdiction of city or town

organizationDetails.evDetails.registrationAgency.state

String

Jurisdiction of State

organizationDetails.evDetails.registrationAgency.country

String

Jurisdiction of Country. (ISO 3166-1 alpha-2 country code)

organizationDetails.evDetails.registrationAgency.city

String

City

organizationDetails.evDetails.registrationAgency.dateOfIncorporation

String

Date of incorporation

organizationDetails.evDetails.registrationAgency.businessCategory

String

Business category. Possible values: [PrivateOrganization, GovernmentEntity, BusinessEntity, NonCommercialEntity]

organizationDetails.evDetails.contractSigner

Object

Contract signer

organizationDetails.evDetails.contractSigner.forename

String

Forename

organizationDetails.evDetails.contractSigner.surname

String

Surname

organizationDetails.evDetails.contractSigner.email

String

Email

organizationDetails.evDetails.contractSigner.phoneNumber

String

Phone Number

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 400
+
+{"id":314,"validationLevel":"OV_SSL","status":"PENDING","alternative":false,"backendId":2146,"backendType":"SASP","settings":{"TRACKING_ID":"1688731626"},"organizationDetails":{"generalDetails":{"legalName":"New org4Test","assumedName":null,"address1":"Deribasovskaya 1","address2":"Street 2","address3":"Street 3","city":"Odesa","stateProvince":"Odeska oblast","postalCode":"65059","country":"UA"}}}
+
+
+
+
+
+

Create external validation assignment

+
+

Creates the assignment to the external organization’s validation

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/assignment
ParameterDescription

orgId

Organization ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

alternative

Boolean

Validation set. Primary (alternative = false) or Secondary (alternative = true). Note: Secondary validation sets are available only for accounts with the corresponding feature enabled.

[]

overwriteIfExists

Boolean

This flag is required to manage the processing when validation with such configuration already exists. By default, overwriting the existing validations is not allowed.

[]

caBackendId

Number

External CA backend ID. Note: All CA backends except 'Sectigo' are considered external.

[]

externalOrgId

String

External CA backend organization ID

[]

externalOrgName

String

External CA backend organization name

[]

validationLevel

String

Validation level

[Must not be null, Allowed values: [OV_SSL, OV_SMIME, EV_SSL]]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2887/validations/assignment' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20758' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+     "validationLevel": "OV_SSL",
+     "externalOrgId": "809849576039",
+     "externalOrgName": "External CA backend organization name",
+     "alternative": false,
+     "caBackendId": 2133,
+     "overwriteIfExists": false
+}
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/organization/v2/2887/validations/304
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created external assignment

+
+
+
+

Change external validation assignment

+
+

Updates the assigned external organization’s validation

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/organization/v2/{orgId}/validations/assignment/{validationId}
ParameterDescription

orgId

Organization ID

validationId

Validation ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

externalOrgId

String

External CA backend organization ID

[]

externalOrgName

String

External CA backend organization name

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/organization/v2/2893/validations/assignment/308' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer20767' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{
+     "externalOrgId": "586703957093",
+     "externalOrgName": "External CA backend organization name"
+}
+'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 202 Accepted
+
+
+
+
+
+
+
+
+

CA Backends

+
+
+

Access to this API is allowed only for MRAO role admins.

+
+
+

List CA Backends

+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/ca-backend/v1' -i -X GET \
+    -H 'login: nick-21161' \
+    -H 'password: Password123!' \
+    -H 'customerUri: ca_backends'
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

Number

CA Backend ID

[].name

String

CA Backend name

[].type

String

CA Backend type. Possible values are: [SASP, PRIVATE_CA, MS_CA, DIGI_CERT, ENTRUST, AWS_PCA, GOOGLE]

[].public

Boolean

Flag indicating whether the CA Backend is public

[].connectorBackendType

String

Applicable only for the connector-based backends. The type of CA backend used in the connector command-line interface.

+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 337
+
+[{"id":2203,"name":"Sectigo Public CA","type":"SASP","public":true},{"id":2204,"name":"Sectigo Private CA","type":"PRIVATE_CA","public":false},{"id":2205,"name":"Microsoft CA","type":"MS_CA","connectorBackendType":"msca","public":false},{"id":2206,"name":"DigiCert CA","type":"DIGI_CERT","connectorBackendType":"digicert","public":true}]
+
+
+
+
+
+
+
+

Reports

+
+
+

Common codes

+
+

Certificate status codes

+
+

These codes can be used as parameters.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Code

Status

0

Any

1

Requested

2

Issued

3

Revoked

4

Expired

5

Enrolled - Pending Download

6

Not Enrolled

7

Awaiting Approval (Deprecated, falls back to "Requested". "Requested" status should be used instead).

8

Approved

9

Applied

10

Downloaded (Deprecated, Issued with "certificateDateAttribute" equal to "Date of Downloading" should be used instead)

11

External (Deprecated, falls back to Issued. Issued with "certificateRequestSource" should be used instead)

+
+
+

Date attribute type codes

+
+

These codes can be used as parameters.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Code

Attribute Type

0

Date of Enrollment

1

Date of Downloading

2

Date of Revocation

3

Date of Expiration

4

Date of Request

5

Date of Issuance

6

Date of Invitation

+
+
+
+

Report APIs

+
+

Activity log report

+
+

Retrieves a log of SCM activities for a customer’s account, including actions on Certificates and actions of Agents.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

from

String

Filters the audit log records by 'created' date. Activity log includes the events that occurred from this date.

ISO format, YYYY-MM-DD. Must be earlier than 'to' date.

to

String

Filters the audit log records by 'created' date. Activity log includes the events that occurred not later than this date.

ISO format, YYYY-MM-DD. Must not be earlier than 'from' date.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/report/v1/activity?output_type=buffered' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20344' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"from":"2019-01-01T00:00:00.000Z","to":"2019-01-31T00:00:00.000Z"}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

statusCode

Number

Report execution status code

reports.[]

Array

Array of reported activity log records with details

reports.[].id

Number

Activity log record ID

reports.[].guid

String

Activity log record GUID

reports.[].accessMethod

String

An access method used to perform the action

reports.[].date

String

Action timestamp

reports.[].address

String

Source IP address of the action request

reports.[].description

String

Activity log record description

reports.[].action

Object

Action info

reports.[].action.id

Number

Action ID

reports.[].action.actionName

String

Action name

reports.[].org

Object

Organization info

reports.[].org.name

String

An organization name which this action is associated with

reports.[].org.address1

String

Organization address line 1

reports.[].org.address2

String

Organization address line 2

reports.[].org.address3

String

Organization address line 3

reports.[].person

Object

Person info

reports.[].person.name

String

A person name which this action is associated with

reports.[].person.email

String

Person email

reports.[].person.guid

String

Person GUID

reports.[].admin

Object

Admin user info

reports.[].admin.login

String

An admin login which this action is associated with

reports.[].admin.fullName

String

Admin full name

reports.[].admin.email

String

Admin email

reports.[].smime

Object

Client certificate info

reports.[].smime.subject

String

Client certificate subject

reports.[].smime.orderNumber

Number

The obsolete parameter for the order identifier under which the client certificate request has been processed. backendCertId should be used instead

reports.[].smime.backendCertId

String

Client certificate ID in enrolling backend

reports.[].ssl

Object

SSL certificate info

reports.[].ssl.commonName

String

SSL certificate common name

reports.[].ssl.orderNumber

Number

The obsolete parameter for the order identifier under which the SSL certificate request has been processed. backendCertId should be used instead

reports.[].ssl.backendCertId

String

SSL certificate ID in enrolling backend

reports.[].ssl.term

Number

SSL certificate term (days)

reports.[].ssl.type

String

SSL certificate profile name

reports.[].notif

Object

Notification info

reports.[].notif.description

String

Notification description

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Disposition: attachment; filename="rest_api_activity.json"
+Cache-Control: must-revalidate
+Pragma: public
+Content-Length: 339
+
+{"statusCode":0,"reports":[{"id":0,"guid":"f308bfa90e5845109adab1d11eaf5ded","action":{"id":0,"actionName":"ClientAdmin: login success"},"admin":{"login":"admin","fullName":"MRAO admin","email":"admin@somecompany.com"},"description":"Login success","accessMethod":"UI access","address":"37.214.176.150","date":"2025-08-15T09:20:13.480Z"}]}
+
+
+
+
+
+

SSL certificates report

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationIds

Array

Unique identifiers of the organizations. The report contains SSL certificates associated with these organizations.

[]

commonName

String

The report will contain only certs with Common Name pattern like this

[Must match the regular expression ^((?!.[><\\].).)*$, Maximum length is 256 characters or can be empty]

externalRequester

String

The report will contain only certs with External Requester pattern like this (case sensitive)

[Maximum length is 512 characters or can be empty]

certificateStatus

Number

Status ID of SSL certificates that are included in the report.

The values applicable to this type of report are: [0(Any), 1(Requested), 2(Issued), 3(Revoked), 4(Expired)]. 11(External) - deprecated, see 'Certificate Status Codes' section for details.

certificateDateAttribute

Number

Unique identifier of the date type.

The values applicable to this type of report are: [2 (Revocation Date), 3 (Expiration Date), 4 (Request Date), 5 (Issuance Date)]

from

String

The report contains SSL certificates which date, defined by 'certificateDateAttribute' request field, is not earlier than this date.

ISO format, YYYY-MM-DD. Must be earlier than 'to' date.

to

String

The report contains SSL certificates which date, defined by 'certificateDateAttribute' request field, is not later than this date.

ISO format, YYYY-MM-DD. Must not be earlier than 'from' date.

certificateRequestSource

Number

The source a certificate has been requested from.

The values applicable to this type of report are:

+

0 (Enrollment Form)

+

1 (Client Admin)

+

2 (Web API)

+

3 (Discovery)

+

4 (Imported)

+

5 (SCEP)

+

7 (MS Agent)

+

9 (Bulk Request)

+

10 (ACME)

+

11 (EST)

+

12 (REST API)

serialNumberFormat

String

Special format of a Serial Number, if required.

If the value specified is 'HEXWithLeadingZeros', then report contains certificate serial numbers in HEX format without leading zeros stripped.

includeIpAddresses

Boolean

Include certificate IP locations. Significantly affects report generation time.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/report/v1/ssl-certificates?output_type=buffered' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20369' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"from":"2019-01-01T00:00:00.000Z","to":"2019-01-31T00:00:00.000Z","organizationIds":[2756],"certificateStatus":1,"certificateDateAttribute":1,"certificateRequestSource":0,"serialNumberFormat":"","includeIpAddresses":false}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

statusCode

Number

Report execution status code

reports.[]

Array

Array of reported SSL certificates with details

reports.[].commonName

String

Certificate common name

reports.[].id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

reports.[].orgId

Number

An organization ID which this certificate is associated with

reports.[].organizationName

String

An organization name which this certificate is associated with

reports.[].city

String

An organization city which this certificate is associated with

reports.[].state

String

An organization state which this certificate is associated with

reports.[].country

String

An organization country which this certificate is associated with

reports.[].status

String

The status of this certificate

reports.[].orderNumber

Number

The obsolete parameter for the order identifier under which the certificate request has been processed. backendCertId should be used instead

reports.[].backendCertId

String

Certificate ID in enrolling backend

reports.[].serverType

String

Deprecated

reports.[].servers

Number

Deprecated

reports.[].typeId

Number

Certificate Profile ID

reports.[].type

String

Certificate Profile name

reports.[].term

Number

Term (days)

reports.[].issuer

String

The subject of the issuing CA certificate

reports.[].requester

String

Requester

reports.[].approver

String

Approver

reports.[].externalRequester

String

External requester

reports.[].comments

String

Comments

reports.[].requested

String

Requested date

reports.[].approved

String

Approved date

reports.[].declined

String

Declined date

reports.[].downloaded

String

Downloaded date

reports.[].expires

String

Expiration date

reports.[].revoked

String

Revocation date

reports.[].replaced

String

Replaced date

reports.[].ipAddresses

String

IP addresses

reports.[].publicKeyAlg

String

Key algorithm (deprecated, see "publicKeyType")

reports.[].publicKeySize

String

Key size (deprecated, see "publicKeyType")

reports.[].publicKeyType

String

Key type. For example: RSA - 2048, EC - P-256.

reports.[].subjAltNames

String

Subject alternative names

reports.[].serialNumber

String

SSL Serial Number

reports.[].requestedVia

String

Requested Via. Possible values: 'Enrollment Form', 'Client Admin', 'Web API', 'Discovery', 'Imported', 'SCEP', 'CD Agent', 'MS Agent', 'MS CA', 'Bulk Request', 'ACME', 'EST', 'REST API'

reports.[].sha1

String

SHA1 Hash

reports.[].md5

String

MD5 Hash

reports.[].customFields.[]

Array

Custom fields

reports.[].customFields.[].name

String

Custom field name

reports.[].customFields.[].value

String

Custom field value

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Disposition: attachment; filename="rest_api_ssl-certificates.json"
+Cache-Control: must-revalidate
+Pragma: public
+Content-Length: 659
+
+{"statusCode":0,"reports":[{"id":310,"type":"SSL SASP -1085798943","typeId":1929,"orgId":2756,"commonName":"ccmqa.com","subjAltNames":"www.test.net; www.plustest.net; www.istest.net","status":"Requested","requester":"20372_nobody@nobody.sectigo.com","organizationName":"org4Test","orderNumber":7344326,"backendCertId":"7344326","servers":1,"serverType":"OTHER","requestedVia":"Enrollment Form","term":365,"comments":"some comments","requested":"2025-08-15T09:20:21.643Z","downloaded":"2019-01-02T00:00:00.000Z","expires":"2026-08-15T09:20:21.619Z","issuer":"issuer","serialNumber":"","city":"Odesa","state":"Odeska oblast","country":"UA","sha1":"AAABBBCCC"}]}
+
+
+
+
+
+

Client certificates report

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationIds

Array

Unique identifiers of the organizations. The report contains Client certificates associated with these organizations.

[]

certificateStatus

Number

Status ID of Client certificates that are included in the report.

The values applicable to this type of report are: [0(Any), 2(Enrolled), 3(Revoked), 4(Expired), 5(Enrolled - Pending Download), 6(Not Enrolled)]. 2(Enrolled) - Former 'Enrolled - Downloaded'. Use with "certificateDateAttribute" equal to "Date of Downloading" to get old semantic. Person list (without client certificates) will be present in the report as well for values: [0(Any), 6(Not Enrolled)]

certificateDateAttribute

Number

Unique identifier of the date type.

The values applicable to this type of report are: [0(Enrolled Date), 1(Downloaded Date), 2(Revocation Date), 3(Expiration Date)]

from

String

The report contains Client certificates which date, defined by 'certificateDateAttribute' request field, is not earlier than this date.

ISO format, YYYY-MM-DD. Must be earlier than 'to' date.

to

String

The report contains Client certificates which date, defined by 'certificateDateAttribute' request field, is not later than this date.

ISO format, YYYY-MM-DD. Must not be earlier than 'from' date.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/report/v1/client-certificates?output_type=buffered' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20347' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"from":"2019-01-01T00:00:00.000Z","to":"2019-01-31T00:00:00.000Z","organizationIds":[2743],"certificateStatus":3,"certificateDateAttribute":1}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

statusCode

Number

Report execution status code

reports.[]

Array

Array of reported client certificates with details

reports.[].id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

reports.[].subject

String

Certificate subject

reports.[].email

String

Certificate email

reports.[].orderNumber

Number

The obsolete parameter for the order identifier under which the certificate request has been processed. backendCertId should be used instead

reports.[].backendCertId

String

Certificate ID in enrolling backend

reports.[].enrolled

String

Enrolled date

reports.[].downloaded

String

Download date

reports.[].expire

String

Expiration date

reports.[].enrollType

String

Enrollment type. Possible values: 'Admin Enroll', 'Self Enroll', 'API Enroll', 'Auto Enroll', 'CSV Enroll', 'SCEP Enroll', 'IdP Enroll', 'MS Agent Enroll', 'Discovery', 'MS CA Enroll', 'Imported', 'EST Enroll', 'REST Enroll API'

reports.[].organization

Object

Organization info

reports.[].organization.id

String

Organization ID

reports.[].organization.name

String

An organization name which this certificate is associated with

reports.[].person

Object

Person info

reports.[].person.name

String

A person name which this certificate is associated with

reports.[].person.email

String

Person email

reports.[].person.guid

String

Person GUID

reports.[].customFields.[]

Array

Custom fields

reports.[].customFields.[].name

String

Custom field name

reports.[].customFields.[].value

String

Custom field value

reports.[].comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Disposition: attachment; filename="rest_api_client-certificates.json"
+Cache-Control: must-revalidate
+Pragma: public
+Content-Length: 483
+
+{"statusCode":0,"reports":[{"id":122,"person":{"name":"Tester","email":"20352_nobody@nobody.sectigo.com","guid":"3095c3e4-f146-3133-a5e6-be134eb2ebe2"},"organization":{"id":"2743","name":"org4Test"},"subject":"test@email","email":"20352_nobody@nobody.sectigo.com","orderNumber":1,"backendCertId":"1","enrolled":"2019-01-02T00:00:00.000Z","downloaded":"2019-01-02T00:00:00.000Z","expire":"2020-01-02T00:00:00.000Z","enrollType":"Self Enroll","comments":"Enrolled by urgent request"}]}
+
+
+
+
+
+

Device certificates report

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

organizationIds

Array

Unique identifiers of the organizations. The report contains Device certificates associated with these organizations.

[]

certificateStatus

Number

Status ID of Device certificates that are included in the report.

The values applicable to this type of report are: [0 (Any), 1 (Requested), 8 (Approved), 9 (Applied), 2 (Issued), 3 (Revoked), 4 (Expired)]. Deprecated statuses: 10 (Downloaded), 7 (Awaiting Approval) - see 'Certificate Status Codes' section for details.

certificateDateAttribute

Number

Unique identifier of the date type.

The values applicable to this type of report are: [2(Revocation Date), 3(Expiration Date), 4(Request Date), 5(Issuance Date)]

from

String

The report contains Device certificates which date, defined by 'certificateDateAttribute' request field, is not earlier than this date.

ISO format, YYYY-MM-DD. Must be earlier than 'to' date.

to

String

The report contains Device certificates which date, defined by 'certificateDateAttribute' request field, is not later than this date.

ISO format, YYYY-MM-DD. Must not be earlier than 'from' date.

serialNumberFormat

String

Special format of a Serial Number, if required.

If the value specified is 'HEXWithLeadingZeros', then report contains certificate serial numbers in HEX format without leading zeros stripped.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/report/v1/device-certificates?output_type=buffered' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20356' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"from":"2025-08-14T09:20:20.741Z","to":"2025-08-16T09:20:20.741Z","certificateStatus":8,"certificateDateAttribute":4,"serialNumberFormat":""}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

statusCode

Number

Report execution status code

reports.[]

Array

Array of reported device certificates with details

reports.[].id

Number

An ID using which this certificate can be renewed or revoked through Enrollment form

reports.[].commonName

String

Certificate common name

reports.[].subject

String

Certificate subject

reports.[].approver

String

Approver

reports.[].city

String

An organization city which this certificate is associated with

reports.[].state

String

An organization state which this certificate is associated with

reports.[].country

String

An organization country which this certificate is associated with

reports.[].deviceCertStatus

String

The status of this certificate

reports.[].serialNumber

String

Device certificate serial number

reports.[].email

String

Certificate email

reports.[].orderNumber

Number

The obsolete parameter for the order identifier under which the certificate request has been processed. backendCertId should be used instead

reports.[].backendCertId

String

Certificate ID in enrolling backend

reports.[].enrolled

String

Enrolled date

reports.[].expire

String

Expiration date

reports.[].enrollType

String

Enrollment type. Possible values: 'API', 'DISCOVERY', 'API_APPROVAL', 'SELF_ENROLLMENT', 'SCEP_ENROLL', 'MS_CA', 'MS_CA_ENROLL_ON_BEHALF', 'UI', 'EST_ENROLL', 'REST_ENROLL', 'IMPORTED'

reports.[].keyAlgorithm

String

Key algorithm (deprecated, see "keyType")

reports.[].keySize

Number

Key size (deprecated, see "keyType")

reports.[].keyType

String

Key type. For example: RSA - 2048, EC - P-256.

reports.[].signatureAlgorithm

String

Signature algorithm

reports.[].certTypeName

String

Certificate Profile name

reports.[].keyUsage

String

Key usage extensions define the purpose of the public key contained in a certificate

reports.[].extendedKeyUsage

String

Extended key usage further refines key usage extensions

reports.[].caId

String

Certificate authority ID

reports.[].caName

String

Certificate authority name

reports.[].organization

Object

Organization info

reports.[].organization.id

String

Organization ID

reports.[].organization.name

String

An organization name which this certificate is associated with

reports.[].customFields.[]

Array

Custom fields

reports.[].customFields.[].name

String

Custom field name

reports.[].customFields.[].value

String

Custom field value

reports.[].comments

String

Certificate comments

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Disposition: attachment; filename="rest_api_device-certificates.json"
+Cache-Control: must-revalidate
+Pragma: public
+Content-Length: 649
+
+{"statusCode":0,"reports":[{"id":135,"commonName":"34356576543tnl54hgnu49u90g","organization":{"id":"2747","name":"org4Test"},"deviceCertStatus":"Approved","subject":"C=UA,ST=Odessa,L=Odessa,O=Test,OU=Test,CN=Test,E=test@test.test","email":"Someone@nobody.sectigo.com","city":"Odesa","state":"Odesa","country":"Ukraine","orderNumber":100500,"backendCertId":"100500","serialNumber":"","certTypeName":"Device cert SASP -1309623208","expire":"2026-08-15T09:20:20.709Z","enrollType":"API","keyAlgorithm":"RSA","keySize":2048,"keyType":"RSA - 2048","signatureAlgorithm":"","approver":"client-admin client-admin","comments":"Enrolled by urgent request"}]}
+
+
+
+
+
+

Domains report

+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/report/v1/domains' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer20362' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response body
+
+
+
{"statusCode":0,"reports":[{"id":404,"name":"scmqa.com","status":"Active","requested":"2025-08-15T09:20:21.198Z","dcvStatus":"Validated","stickyUntil":"2019-01-03T00:00:00.000Z"}]}
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

statusCode

Number

Report execution status code

reports.[]

Array

Array of reported domain records with details

reports.[].id

Number

Domain id

reports.[].name

String

Domain name

reports.[].status

String

Domain state. Available values are: [Suspended, Active]

reports.[].requested

String

Domain requested date

reports.[].stickyUntil

String

DCV expiration date

reports.[].dcvStatus

String

Domain control validation status. Possible values: 'Not Initiated', 'Validated', 'Action Required', 'Expired'

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Disposition: attachment; filename="rest_api_domains.json"
+Cache-Control: must-revalidate
+Pragma: public
+Content-Length: 180
+
+{"statusCode":0,"reports":[{"id":404,"name":"scmqa.com","status":"Active","requested":"2025-08-15T09:20:21.198Z","dcvStatus":"Validated","stickyUntil":"2019-01-03T00:00:00.000Z"}]}
+
+
+
+
+
+
+
+
+

ACME

+
+
+

Sectigo Public ACME

+
+

List Sectigo Public ACME servers

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

name

ACME server name

url

ACME server URL

certValidationType

ACME server validation type. Values: [DV, OV, EV]

caId

ACME server CA ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/server?position=0&size=10&name=OV+ACME+Server&url=https%3A%2Facmeserverfortest-OV&certValidationType=OV&caId=40485' -i -X GET \
+    -H 'login: nick-20110' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20109'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of ACME servers

[].name

String

ACME server name

[].certValidationType

String

ACME server validation type. Values: [DV, OV, EV]

[].url

String

ACME server URL

[].caId

Number

ACME server CA ID

[].singleProductId

Number

ACME server single product ID

[].multiProductId

Number

ACME server multi product ID

[].wcProductId

Number

ACME server WC product ID

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 169
+
+[{"url":"https:/acmeserverfortest-OV","caId":40485,"name":"OV ACME Server","singleProductId":66362,"multiProductId":23234,"wcProductId":14608,"certValidationType":"OV"}]
+
+
+
+
+
+

List Sectigo Public ACME accounts

+
+

V2

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

organizationId

Organization ID. You can append '%2C-2' (e.g. organizationId=105%2C-2) URL-encoded suffix for none departments selection, only organization(e.g. with ID=105) itself.

name

ACME account name

acmeServer

ACME account server name

certValidationType

ACME account server validation type. Values: [DV, OV, EV]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account?position=0&size=10&organizationId=2679&name=OV+ACME+Account&acmeServer=OV+ACME+Server' -i -X GET \
+    -H 'login: nick-19962' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19955'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME accounts existing on Sectigo public CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of ACME accounts

[].id

Number

ACME account entity ID

[].name

String

ACME account name

[].macKey

String

ACME account HMAC key

[].macId

String

ACME account key ID

[].acmeServer

String

ACME account server name

[].organizationId

Number

ACME account organization ID

[].certValidationType

String

ACME account server validation type. Values: [DV, OV, EV]

[].accountId

String

ACME account ID

[].validationId

String

OV anchor certificate ID for OV accounts and EV tracking ID for EV accounts

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 338
+
+[{"id":97,"accountId":"7df9646f-631c-44f4-a0bd-cd30bec66846","macId":"7df9646f-631c-44f4-a0bd-cd30bec66846","macKey":"58da39fc-cea4-44ad-a56e-1db0dc7fd2d1","acmeServer":"OV ACME Server","name":"OV ACME Account","organizationId":2679,"certValidationType":"OV","ovOrderNumber":686756872,"ovAnchorID":"686756872","validationId":"686756872"}]
+
+
+
+
+

V1 - Deprecated

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

organizationId

Organization ID. You can append '%2C-2' (e.g. organizationId=105%2C-2) URL-encoded suffix for none departments selection, only organization(e.g. with ID=105) itself.

name

ACME account name

acmeServer

ACME account server name

certValidationType

ACME account server validation type. Values: [DV, OV, EV]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account?position=0&size=10&organizationId=2733&name=OV+ACME+Account&acmeServer=OV+ACME+Server' -i -X GET \
+    -H 'login: nick-20306' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20299'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME accounts existing on SASP public CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of ACME accounts

[].id

Number

ACME account entity ID

[].name

String

ACME account name

[].macKey

String

ACME account HMAC key

[].macId

String

ACME account key ID

[].acmeServer

String

ACME account server name

[].organizationId

Number

ACME account organization ID

[].certValidationType

String

ACME account server validation type. Values: [DV, OV, EV]

[].accountId

String

ACME account ID

[].ovOrderNumber

Number

OV order number (deprecated, see 'ovAnchorID')

[].ovAnchorID

String

OV anchor certificate ID.

[].validationId

String

ACME account’s organization pre-validation ID.

[].domains[]

Array

ACME account domains

[].domains[].name

String

ACME account domain name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 414
+
+[{"id":150,"accountId":"4c230117-e9b2-4c9c-9241-86b4e7e93647","macId":"4c230117-e9b2-4c9c-9241-86b4e7e93647","macKey":"9da014d0-f065-473f-80bb-54b11fc940ba","acmeServer":"OV ACME Server","name":"OV ACME Account","organizationId":2733,"certValidationType":"OV","ovOrderNumber":2121298300,"ovAnchorID":"2121298300","validationId":"2121298300","domains":[{"name":"domain.ccmqa.com"},{"name":"sub.domain.ccmqa.com"}]}]
+
+
+
+
+
+

Get Sectigo Public ACME account details

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}
ParameterDescription

id

ACME account entity ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/93' -i -X GET \
+    -H 'login: nick-19948' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19941' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

ACME account entity ID

name

String

ACME account name

macKey

String

ACME account HMAC key

macId

String

ACME account key ID

acmeServer

String

ACME account server name

organizationId

Number

ACME account organization ID

certValidationType

String

ACME account server validation type. Values: [DV, OV, EV]

accountId

String

ACME account ID

validationId

String

OV anchor certificate ID for OV accounts and EV tracking ID for EV accounts

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 333
+
+{"id":93,"accountId":"3157542e-215d-4166-9712-ffab6f80b950","macId":"3157542e-215d-4166-9712-ffab6f80b950","macKey":"bd4d8b1c-afa5-4005-b8fa-deeb796705e7","acmeServer":"EV ACME Server","name":"EV ACME Account","organizationId":2677,"certValidationType":"EV","ovOrderNumber":65690742,"ovAnchorID":"65690742","validationId":"65690742"}
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/account/{id}
ParameterDescription

id

ACME account entity ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account/146' -i -X GET \
+    -H 'login: nick-20292' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20285' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

ACME account entity ID

name

String

ACME account name

macKey

String

ACME account HMAC key

macId

String

ACME account key ID

acmeServer

String

ACME account server name

organizationId

Number

ACME account organization ID

certValidationType

String

ACME account server validation type. Values: [DV, OV, EV]

accountId

String

ACME account ID

ovOrderNumber

Number

For OV accounts only: OV order number (deprecated, see 'ovAnchorID')

ovAnchorID

String

For OV accounts only: OV anchor certificate ID.

validationId

String

ACME account’s organization pre-validation ID.

domains[]

Array

ACME account domains

domains[].name

String

ACME account domain name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 374
+
+{"id":146,"accountId":"c65f387f-5e4e-4389-8494-1cf6f68c46a9","macId":"c65f387f-5e4e-4389-8494-1cf6f68c46a9","macKey":"1367eafe-c323-4df8-9f08-7191b32364fe","acmeServer":"EV ACME Server","name":"EV ACME Account","organizationId":2731,"certValidationType":"EV","ovOrderNumber":24117951,"ovAnchorID":"24117951","validationId":"24117951","domains":[{"name":"domain.ccmqa.com"}]}
+
+
+
+
+
+

Create Sectigo Public ACME account

+
+

V2

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

ACME account name

[]

acmeServer

String

ACME account server name

[]

organizationId

Number

ACME account organization ID

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-19831' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19824' \
+    -d '{"acmeServer":"EV ACME Server","name":"EV ACME Account","organizationId":2661}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

New ACME account resource added on Private CA

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/acme/v2/account/71
+
+
+
+
+

V1 - Deprecated

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

ACME account name

[]

acmeServer

String

ACME account server name

[]

organizationId

Number

ACME account organization ID

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20249' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20242' \
+    -d '{"acmeServer":"EV ACME Server","name":"EV ACME Account","organizationId":2725}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

New ACME account resource added on Private CA

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/acme/v1/account/139
+
+
+
+
+
+

Update Sectigo Public ACME account details

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

ACME account name

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/78' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-19874' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19867' \
+    -d '{"name":"EV ACME Account Updated"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/account/{id}
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

ACME account name

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account/155' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20334' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20327' \
+    -d '{"name":"EV ACME Account Updated"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete Sectigo Public ACME account

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}
ParameterDescription

id

ID of ACME account that being deleted

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/73' -i -X DELETE \
+    -H 'login: nick-19846' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19839'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/account/{id}
ParameterDescription

id

ID of ACME account that being deleted

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account/141' -i -X DELETE \
+    -H 'login: nick-20264' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20257'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Add domains to Sectigo Public ACME account

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}/domain
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains[]

Array

Domains list

[Must not be empty]

domains[].name

String

Domain name

[Must not be blank, Size must be between 1 and 1024 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/83/domain' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-19888' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19881' \
+    -d '{"domains":[{"name":"domain.ccmqa.com"},{"name":"sub.domain.ccmqa.com"}]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

notAddedDomains[]

Array

Domains not added to the ACME account upon update operation

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 2
+
+{}
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/account/{id}/domains
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains[]

Array

Domains list

[Must not be empty]

domains[].name

String

Domain name

[Must not be blank, Size must be between 1 and 1024 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account/131/domains' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20217' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20210' \
+    -d '{"domains":[{"name":"domain.ccmqa.com"},{"name":"sub.domain.ccmqa.com"}]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

notAddedDomains[]

Array

Domains not added to the ACME account upon update operation

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 2
+
+{}
+
+
+
+
+
+

Remove domains from Sectigo Public ACME account

+
+

V2

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}/domain
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains[]

Array

Domains list

[Must not be empty]

domains[].name

String

Domain name

[Must not be blank, Size must be between 1 and 1024 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/91/domain' -i -X DELETE \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-19934' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19927' \
+    -d '{"domains":[{"name":"domain.ccmqa.com.ua"},{"name":"sub.domain.ccmqa.com"},{"name":"unknown.ccmqa.com"}]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

notRemovedDomains[]

Array

Domains not removed from the ACME account upon update operation

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 65
+
+{"notRemovedDomains":["domain.ccmqa.com.ua","unknown.ccmqa.com"]}
+
+
+
+
+

V1 - Deprecated

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/account/{id}/domains
ParameterDescription

id

ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

domains[]

Array

Domains list

[Must not be empty]

domains[].name

String

Domain name

[Must not be blank, Size must be between 1 and 1024 inclusive]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/account/144/domains' -i -X DELETE \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20278' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20271' \
+    -d '{"domains":[{"name":"domain.ccmqa.com.ua"},{"name":"sub.domain.ccmqa.com"},{"name":"unknown.ccmqa.com"}]}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

notRemovedDomains[]

Array

Domains not removed from the ACME account upon update operation

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 65
+
+{"notRemovedDomains":["domain.ccmqa.com.ua","unknown.ccmqa.com"]}
+
+
+
+
+
+

List Sectigo Public ACME account’s domains

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}/domain
ParameterDescription

id

SCM internal ID of ACME account whose domains are requested.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

name

The RegExp that can be used as a filter to get ACME account domains whose names match against. Special characters should be URL-encoded e.g. \. ⇒ %5C%2E

expiresWithinNextDays

Number of days(from current date) that is used as a filter to get ACME account’s domains whose 'validUntil' field(date) falls within the specifies time period, so during which ACME account’s domain validation will be or already has(in case of negative number) expired.Zero number of days means today, negative number of days means before today, positive number of days means after today.

stickyExpiresWithinNextDays

Number of days(from current date) that is used as a filter to get ACME account’s domains whose 'stickyUntil' field(date) falls within the specifies time period, so during which ACME account domain validation sticky will be or already has(in case of negative number) expired. Zero number of days means today, negative number of days means before today, positive number of days means after today.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/106/domain?position=0&size=10&name=.*&expiresWithinNextDays=365&stickyExpiresWithinNextDays=365' -i -X GET \
+    -H 'login: nick-20004' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19997'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME account’s domains existing on Sectigo public CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

ACME account’s domains

[].name

String

ACME account domain name

[].validUntil

String

ACME account domain validation until date in ISO-8601 format

[].stickyUntil

String

ACME account domain validation sticky until date in ISO-8601 format.

[].validationId

String

ACME account validated domain OV/EV order number from Sectigo public CA

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 391
+
+[{"name":"domain.ccmqa.com","validUntil":"2026-08-15T09:19:52.732Z","stickyUntil":"2026-08-15T09:19:52.732Z","ovAnchorOrderNumber":116084230,"ovAnchorID":"116084230","validationId":"116084230"},{"name":"sub.domain.ccmqa.com","validUntil":"2026-08-15T09:19:52.732Z","stickyUntil":"2026-08-15T09:19:52.732Z","ovAnchorOrderNumber":116084230,"ovAnchorID":"116084230","validationId":"116084230"}]
+
+
+
+
+
+

List Sectigo Public ACME account’s clients

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}/client
ParameterDescription

id

SCM internal ID of ACME account whose clients are requested.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

userAgent

The any substring of ACME account client’s 'userAgent' field to match against

ipAddress

The any substring of ACME account client’s 'ipAddress' field to match against

status

The status string of ACME account client’s 'status' field to equal

lastActivityWithinPrevDays

Number of days(from end of the current day to the past) that is used as a filter to get ACME account’s clients whose 'lastActivity' field(date) falls within the specifies time period, so during which ACME account’s client was last active (connected/requested the Sectigo public CA).

contacts

The any substring of ACME account client’s 'contacts' field to match against

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/100/client?position=0&size=10&userAgent=acme&ipAddress=10.1&contacts=%40contact.test&status=valid&lastActivityWithinPrevDays=1' -i -X GET \
+    -H 'login: nick-19976' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19969'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME account’s clients existing on Sectigo public CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

ACME account’s clients

[].accountId

String

ACME account client’s accountID. Note this identifier is concerning to the ACME client itself, but not to its parent ACME account.

[].userAgent

String

ACME account client’s user agent name

[].ipAddress

String

IP address of host from where the ACME account’s client was last active

[].status

String

ACME account client’s status

[].lastActivity

String

Date when ACME account’s client was last active

[].contacts

String

ACME account client’s contacts

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 415
+
+[{"accountId":"7f237ca1-fd84-4a0b-85e7-237398bc4d0a","ipAddress":"1.1.1.1","userAgent":"lego-cli/4.2.0 xenolf-acme/4.2.0 (release; windows; amd64)","status":"valid","lastActivity":"2025-08-15T09:19:51.978Z"},{"accountId":"4063b8fe-deaf-4b1a-9772-1cfde9eb2e89","ipAddress":"1.1.1.1","userAgent":"lego-cli/4.2.0 xenolf-acme/4.2.0 (release; windows; amd64)","status":"valid","lastActivity":"2025-08-15T09:19:51.978Z"}]
+
+
+
+
+
+

Delete Sectigo Public ACME account’s client

+
+

Method is no longer supported. Please, use "Deactivate Sectigo Public ACME account’s client" method instead.

+
+
+
+

Deactivate Sectigo Public ACME account’s client

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/acme/v2/account/{id}/client/{clientId}
ParameterDescription

id

ID of ACME account whose client will be deactivated

clientId

UUID of ACME account’s client that being deactivated (accountId)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v2/account/85/client/9a13ae55-35dd-4d21-8592-42e85bb14a48' -i -X PUT \
+    -H 'login: nick-19906' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst19899'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Universal ACME

+
+

List Universal ACME accounts

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

organizationId

Organization ID

name

Universal ACME account name

acmeServer

Universal ACME account server name

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account?position=0&size=10&organizationId=2713&name=Universal+ACME+Account&acmeServer=Universal+ACME+Server' -i -X GET \
+    -H 'login: nick-20175' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20170'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME accounts existing on Private CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Universal ACME accounts

[].id

Number

Universal ACME account entity ID

[].name

String

Universal ACME account name

[].macKey

String

Universal ACME account HMAC key

[].macId

String

Universal ACME account key ID

[].acmeServer

String

Universal ACME account server name

[].organizationId

Number

Universal ACME account organization ID

[].accountId

String

Universal ACME account ID

[].profileName

String

Universal ACME account profile name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 218
+
+[{"id":81,"accountId":"339a6a64-8411-41f4-a857-1fd653d628a5","macId":"","macKey":"","acmeServer":"Universal ACME Server","name":"Universal ACME Account","organizationId":2713,"profileName":"SSL PRIVATE_CA 1011280548"}]
+
+
+
+
+
+

Get Universal ACME account details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/pca/account/{id}
ParameterDescription

id

Universal ACME account entity ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account/80' -i -X GET \
+    -H 'login: nick-20165' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20160' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Universal ACME account entity ID

name

String

Universal ACME account name

macKey

String

Universal ACME account HMAC key

macId

String

Universal ACME account key ID

acmeServer

String

Universal ACME account server name

organizationId

Number

Universal ACME account organization ID

accountId

String

Universal ACME account ID

profileName

String

Universal ACME account profile name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 216
+
+{"id":80,"accountId":"b1ddd55e-e80d-4788-8bfb-1ae6f6c0532e","macId":"","macKey":"","acmeServer":"Universal ACME Server","name":"Universal ACME Account","organizationId":2711,"profileName":"SSL PRIVATE_CA 2100617111"}
+
+
+
+
+
+

Create Universal ACME account

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Universal ACME account name

[Must not be blank, Size must be between 1 and 128 inclusive]

acmeServer

String

Universal ACME account server name

[Must not be blank, Size must be between 1 and 1024 inclusive]

organizationId

Number

Universal ACME account organization ID

[Must be at least 1, Must not be null]

profileName

String

Universal ACME account profile name

[Must not be empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account' -i -X POST \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20126' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20121' \
+    -d '{"acmeServer":"Universal ACME Server","name":"Universal ACME Account","organizationId":2703,"profileName":"SSL PRIVATE_CA 1607375404"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

New ACME account resource added on Private CA

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/acme/v1/pca/account/76
+
+
+
+
+
+

Update Universal ACME account details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/pca/account/{id}
ParameterDescription

id

Universal ACME account entity ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Universal ACME account name

[]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account/84' -i -X PUT \
+    -H 'Content-Type: application/json' \
+    -H 'login: nick-20205' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20200' \
+    -d '{"name":"Universal ACME Account Updated"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete Universal ACME account

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/pca/account/{id}
ParameterDescription

id

ID of Universal ACME account that being deleted

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account/78' -i -X DELETE \
+    -H 'login: nick-20145' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20140'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

List Universal ACME account’s clients

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/acme/v1/pca/account/{id}/client
ParameterDescription

id

SCM internal ID of Universal ACME account whose clients are requested.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

the first position (entry) to return from the results of the query

size

Count of entries

userAgent

The any substring of Universal ACME account client’s 'userAgent' field to match against

ipAddress

The any substring of Universal ACME account client’s 'ipAddress' field to match against

status

The status string of Universal ACME account client’s 'status' field to equal

lastActivityWithinPrevDays

Number of days(from end of the current day to the past) that is used as a filter to get Universal ACME account’s clients whose 'lastActivity' field(date) falls within the specifies time period, so during which Universal ACME account’s client was last active (connected/requested the private CA).

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account/82/client?position=0&size=10&userAgent=acme&ipAddress=10.1&status=valid&status=pending&lastActivityWithinPrevDays=1' -i -X GET \
+    -H 'login: nick-20185' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20180'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered ACME account’s clients existing on Private CA side

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

Universal ACME account’s clients

[].accountId

String

Universal ACME account client’s accountID. Note this identifier is concerning to the ACME client itself, but not to its parent Universal ACME account.

[].userAgent

String

Universal ACME account client’s user agent name

[].ipAddress

String

IP address of host from where the Universal ACME account’s client was last active

[].status

String

Universal ACME account client’s status

[].lastActivity

String

Date when Universal ACME account’s client was last active

[].contacts

String

Contact(s) concerning of ACME client operations

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 525
+
+[{"accountId":"FmcZgzSqt6TpAtQFAAAAAA==","ipAddress":"10.17.7.152","userAgent":"lego-cli/4.2.0 xenolf-acme/4.2.0 (release; windows; amd64)","status":"valid","lastActivity":"2025-08-15T09:05:54.985Z","contacts":"email@ccmqa.com"},{"accountId":"FswPwHxLUh-caoO3AAAAAA==","ipAddress":"10.18.8.143","userAgent":"CertbotACMEClient/1.22.0 (certbot; Ubuntu 18.04.6 LTS) Authenticator/standalone Installer/None (certonly; flags: n) Py/3.6.9","status":"pending","lastActivity":"2025-08-15T09:05:54.985Z","contacts":"email@ccmqa.com"}]
+
+
+
+
+
+

Delete Universal ACME account’s client

+
+

Method is no longer supported. Please, use "Deactivate Universal ACME account’s client" method instead.

+
+
+
+

Deactivate Universal ACME account’s client

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/acme/v1/pca/account/{id}/client/{clientId}
ParameterDescription

id

ID of Universal ACME account whose client will being deleted

clientId

UUID of Universal ACME account’s client that being deleted (accountId)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/acme/v1/pca/account/77/client/FmcZgzSqt6TpAtQFAAAAAA==' -i -X PUT \
+    -H 'login: nick-20135' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst20130'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+
+
+

Network Agents

+
+
+

Used to perform operations on Network Agents.

+
+
+

View Network Agents

+
+

List Network Agents

+
+

List all Network Agents that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

The start position (offset) to get sub-list (page) of Network agents starting from. Optional.

size

The max count (page size) of Network agents to be returned in sub-list (page) starting from 'position'. Max value = 200. Optional.

name

The whole or part of Network agent name to match against to anywhere in the name with insensitive case compare when listing. Optional.

orgId

Matching against ID of Organization to which the Network agent belongs. Optional.

includeDepOfOrg

Denotes whether need to consider the departments of organization specified by 'orgId' parameters (if any) to match against when listing. Optional.

active

Return active Network agents only (if =true), not active (if = false), or all (if not specified at all). Optional.

version

The whole or part of Network agent version to match against to anywhere in the version. Optional.

status

Return Network agents with specified status only. Optional. Allowed values: [NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network?size=200&position=0&orgId=1054&includeDepOfOrg=false&version=1&status=CONNECTED&active=true&name=-' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1797' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1796'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered Network agents.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Network agents according to filter request parameters

[].id

Number

Network agent entity ID

[].version

String

Network agent version

[].name

String

Network agent name

[].active

Boolean

Whether Network agent active(=true), or disabled(=false)

[].status

String

Network agent current status. Possible values: [NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 3
+Content-Type: application/json;charset=UTF-8
+Content-Length: 258
+
+[{"version":"1.5","status":"CONNECTED","id":107,"active":true,"name":"NetworkAgent-15"},{"version":"1.3","status":"CONNECTED","id":95,"active":true,"name":"NetworkAgent-3"},{"version":"1.6","status":"CONNECTED","id":98,"active":true,"name":"NetworkAgent-6"}]
+
+
+
+
+
+

Count Network Agents

+
+

Count all Network Agents that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

countOnly

Denotes that expecting a total count only to be returned in 'X-Total-Count' response header, without return a really data in response body. Required with value =true.

name

The whole or part of Network agent name to match against to anywhere in the name with insensitive case compare when counting. Optional.

orgId

Matching against ID of Organization to which the Network agent belongs. Optional.

includeDepOfOrg

Denotes whether need to consider the departments of organization specified by 'orgId' parameters (if any) to match against when counting. Optional.

active

Count active Network agents only (if =true), not active (if = false), or all (if not specified at all). Optional.

version

The whole or part of Network agent version to match against to anywhere in the version. Optional.

status

Return Network agents with specified status only. Optional. Allowed values: [NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network?countOnly=true&orgId=1027&includeDepOfOrg=false&version=1&status=CONNECTED&active=true&name=-' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1764' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1763'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered Network agents.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 3
+
+
+
+
+
+

Get Network Agent details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{id}
ParameterDescription

id

ID(90) of existed Network agent to get its details. Must be zero or positive integer.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/90' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1788' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1787'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Network agent ID

version

String

Network agent version

os

String

Operating system on host where Network agent installed

name

String

Network agent name

comments

String

Comments about Network agent

active

Boolean

Either Network agent active or not(disabled)

status

String

Network agent current status. Possible values: [NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

localIp

String

IP addresses list Network agent installed on

lastActivity

String

Last Network agent activity timestamp. Optional.

orgId

Number

The ID of organization the Network agent belongs to

autoUpdate

Boolean

Enabled or disabled Network agent auto update

secretKey

String

Secret key to authenticate Network agent on SCM

installationToken

String

The token which can be used during an installation of Network agent at client’s environment. Provided for new Network agents only or those which were not connected to SCM yet. Optional.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 467
+
+{"id":90,"version":"1.1","os":"WINDOWS","autoUpdate":false,"localIp":"192.168.2.1","status":"NOT_AVAILABLE","installationToken":"eyJzY21VcmwiOiJodHRwczovL2NlcnQtbWFuYWdlci5jb20iLCJjdXN0b21lclVyaSI6ImNzdDE3ODciLCJzZWNyZXQiOiJTb21lVmFsdWVPZlNlY3JldEtleTEiLCJrZXlzdG9yZVBhc3N3b3JkIjoiUFVjZVFRZjBHdnU5N3huV2VaWjJ3czNrVHY1SHp0aEsifQ==","secretKey":"SomeValueOfSecretKey1","orgId":1046,"comments":"Some comments about Network agent 1","active":true,"name":"NetworkAgent 1"}
+
+
+
+
+
+
+

Manage Network Agents

+
+

Add Network Agent

+
+

Adds a new Network Agent and returns the installation token needed for agent installation.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Network agent name

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Must not be blank, Size must be between 1 and 128 inclusive]

comments

String

Network agent comments

[Maximum length is 256 characters or can be empty, Optional]

orgId

Number

Network agent organization ID

[Must be at least 0, Must not be null]

active

Boolean

Denotes either Network agent active or not.

[Must not be null]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick-1773' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1772' \
+    -d '{"name":"NetworkAgent-1","active":true,"comments":"This is the first network agent discovered on sub-net ... and located at ...","orgId":1036}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

The location of the newly added network agent resource in SCM.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

installationToken

String

The token which can be used during an installation of Network agent at client’s environment.

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/agent/v1/network/85
+Content-Type: application/json;charset=UTF-8
+Content-Length: 212
+
+{"installationToken":"eyJzY21VcmwiOiJodHRwczovL2NlcnQtbWFuYWdlci5jb20iLCJjdXN0b21lclVyaSI6ImNzdDE3NzIiLCJzZWNyZXQiOiJjeXlhb3dRNTl2WkR4LU11VWhDWiIsImtleXN0b3JlUGFzc3dvcmQiOiJxUUVnOFU5YzE4ZnE2UTJrU1NEQllBPT0ifQ=="}
+
+
+
+
+
+

Update Network Agent details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{id}
ParameterDescription

id

ID(115) of existed Network agent to update. Must be zero or positive integer.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

New name for Network agent.

[Must be null or not blank, Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Size must be between 1 and 128 inclusive, Optional]

comments

String

New comments for Network agent.

[Maximum length is 256 characters or can be empty, Optional]

active

Boolean

New state of Network agent that denotes either it should be active or not.

[Optional]

secretKey

String

New secret key used for Network agent lookup and authorization.

[Size must be between 10 and 128 inclusive, Optional]

keystorePwd

String

New password for the local keystore where Network agent stores certificates and keys.

[Size must be between 10 and 128 inclusive, Optional]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/115' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick-1806' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1805' \
+    -d '{"name":"NetworkAgent-2","active":true,"comments":"This is the second network agent discovered on sub-net ... and located at ...","secretKey":"Ap@rticul@rZecretQey","keystorePwd":"Ap@rticul@rQeySt0rePwd"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete Network Agent

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{id}
ParameterDescription

id

ID(88) of existed Network agent to delete. Must be zero or positive integer.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/88' -i -X DELETE \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1782' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1781'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+

Manage servers

+
+

List servers

+
+

List all servers that match the requested filter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server
ParameterDescription

agentId

ID(114) of existed Network agent to get count of its discovered servers.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

The start position (offset) to get a sub-list (page) of servers discovered by Network agent. Optional.

size

The max count (page size) of servers discovered by Network agent to be returned in sub-list (page) starting from 'position'. Max value = 200. Optional.

name

The whole or part of name of server discovered by Network agent to match against to anywhere in the server name with insensitive case compare when counting. Optional.

vendor

To match against a Vendor of server discovered by Network agent. Possible values: [APACHE_2, IIS, TOMCAT, F5_BIG_IP]. Optional.

status

To match against a State of server discovered by Network agent. Possible values: [INIT, ACTIVE, INACTIVE, RESTART_REQUIRED, RESTARTING]. Optional.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/114/server?size=200&position=0&name=1&vendor=TOMCAT&status=INIT' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1803' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1802'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered servers discovered by Network agent.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of servers discovered by Network agent according to filter request parameters.

[].id

Number

ID of server discovered by Network agent

[].name

String

Name of server discovered by Network agent

[].active

Boolean

Whether server discovered by Network agent active(=true), or disabled(=false)

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json;charset=UTF-8
+Content-Length: 109
+
+[{"id":96,"active":false,"name":"DiscoveredServer 19"},{"id":88,"active":false,"name":"DiscoveredServer 11"}]
+
+
+
+
+
+

Count servers

+
+

Count all servers that match the requested filter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server
ParameterDescription

agentId

ID(84) of existed Network agent to get count of its discovered servers.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

countOnly

Denotes that expecting a total count only to be returned in 'X-Total-Count' response header, without return a really data in response body. Required with value =true.

name

The whole or part of name of server discovered by Network agent to match against to anywhere in the server name with insensitive case compare when counting. Optional.

vendor

To match against a Vendor of server discovered by Network agent. Possible values: [APACHE_2, IIS, TOMCAT, F5_BIG_IP]Optional.

status

To match against a State of server discovered by Network agent. Possible values: [INIT, ACTIVE, INACTIVE, RESTART_REQUIRED, RESTARTING]. Optional.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/84/server?countOnly=true&name=1&vendor=TOMCAT&status=INIT' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1770' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1769'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered servers discovered by Network agent.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+
+
+
+
+
+

Get server details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{id}
ParameterDescription

agentId

ID(91) of existed Network agent to get details of its discovered server. Must be zero or positive integer.

id

ID(75) of existed server discovered by Network agent to get a few more its details. Must be zero or positive integer.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/91/server/75' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1791' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1790'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

ID of server discovered by Network agent

name

String

Name of server discovered by Network agent

vendor

String

Vendor of server discovered by Network agent. Possible values: [APACHE_2, IIS, TOMCAT, F5_BIG_IP]

connectionType

String

Connection type to server discovered by Network agent. Possible values: [LOCAL, LOCAL_LEGACY_NATIVE_API, REMOTE_REST_API, REMOTE_SSH, REMOTE_WIN_RM, REMOTE_LEGACY_NATIVE_API], vendor dependent

status

String

The state of server discovered by Network agent. Possible values: [INIT, ACTIVE, INACTIVE, RESTART_REQUIRED, RESTARTING]

ip

String

Hostname or IP of server discovered by Network agent

port

Number

Port number on server discovered by Network agent

path

String

Path to root directory where server discovered by Network agent is installed.

altPathForCert

String

Alternative path to a directory where server discovered by Network agent stores certificates.

privateKeyPath

String

Path to a directory where Network agent stores private key to authenticate on discovered server.

username

String

Username(login) to gain access to server discovered by Network agent.

errorMessage

String

The error occurred when Network agent was executing a command intended for this discovered server.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 314
+
+{"id":75,"vendor":"APACHE_2","connectionType":"LOCAL","name":"DiscoveredServer 1","path":"C:\\Windows\\System32\\inetsrv\\1","status":"INIT","errorMessage":"Some 1 error(s) occurred.","ip":"192.168.2.101","port":8081,"altPathForCert":"C:\\Users\\SomeUser\\Certs\\1","privateKeyPath":"C:\\Users\\SomeUser\\.ssh\\1"}
+
+
+
+
+
+

Add server

+
+

Add a new server to a Network Agent.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server
ParameterDescription

agentId

ID(86) of existed Network agent to add a newly created server to it as discovered one.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Name of server discovered by Network agent

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Must not be blank, Size must be between 1 and 512 inclusive]

vendor

String

Vendor of server discovered by Network agent

[Must not be null, Possible values: [APACHE_2, IIS, TOMCAT, F5_BIG_IP]]

connectionType

String

Connection type to server discovered by Network agent

[Possible values: [LOCAL, LOCAL_LEGACY_NATIVE_API, REMOTE_REST_API, REMOTE_SSH, REMOTE_WIN_RM, REMOTE_LEGACY_NATIVE_API], vendor related.]

ip

String

Hostname or IP address of server that’s creating as one discovered by Network agent

[Maximum length is 255 characters or can be empty, Required for a remote server.]

port

Number

Port number on server discovered by Network agent

[Must be at least 0, Required for a remote server and for all except 'IIS' vendors.]

path

String

Path to root directory(in case of 'TOMCAT' vendor) or to the 'apachectl' executable(in case of 'APACHE_2' vendor) of server discovered by Network agent.

[Maximum length is 512 characters or can be empty, Can be specified for 'APACHE_2' and 'TOMCAT' vendors only. Optional.]

altPathForCert

String

Alternative path to a directory where server discovered by Network agent stores certificates.

[Can be specified for a remote server and for 'APACHE_2' vendor only. Optional.]

privateKeyPath

String

Path to a directory where Network agent stores private key to authenticate on discovered server.

[Maximum length is 128 characters or can be empty, Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'passPhrase' but not with 'username'/'password' parameters and not with 'storeName'/'storeCredId' parameters. Optional.]

passPhrase

String

Passphrase to gain access to keystore where Network agent preserves the private key to authenticate on discovered server.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Used together with 'privateKeyPath' but not with 'username'/'password' parameters and not with 'storeName'/'storeCredId' parameters. Optional.]

username

String

Username(login) to gain access to server discovered by Network agent.

[Maximum length is 64 characters or can be empty, Can be specified for a remote server and for all vendors. Must be used in conjunction with 'password' but not with 'privateKeyPath'/'passPhrase' parameters and not with 'storeName'/'storeCredId' parameters. Optional.]

password

String

Password for username to gain access to server discovered by Network agent.

[Can be specified for a remote server and for all vendors. Used together with 'username' but not with 'privateKeyPath'/'passPhrase' parameters and not with 'storeName'/'storeCredId' parameters. Optional.]

storeName

String

Store name to gain access to server discovered by Network agent.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'storeCredId' but not with 'username'/'password' parameters and not with 'privateKeyPath'/'passPhrase' parameters. Optional.]

storeCredId

String

Store credential ID to gain access to server discovered by Network agent.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'storeName' but not with 'username'/'password' parameters and not with 'privateKeyPath'/'passPhrase' parameters. Optional.]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/86/server' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick-1776' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1775' \
+    -d '{"name":"NetworkAgent-1","vendor":"TOMCAT","connectionType":"LOCAL_LEGACY_NATIVE_API","path":"C:\\Windows\\System32\\inetsrv","username":"SomeUser","password":"S0meYserPwB"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

The location of the newly created server resource added to the Network agent as one discovered on client side.

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/agent/v1/network/86/server/73
+
+
+
+
+
+

Update server details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{id}
ParameterDescription

agentId

ID(116) of existed Network agent to update details of its discovered server. Must be zero or positive integer.

id

ID(98) of existed server discovered by Network agent to update. Must be zero or positive integer.

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Name of server discovered by Network agent

[Must match the regular expression ((?!.[>|<|!|@|#|\$|\%|\|\|\(|\)|~|\?|/|\|\&|\_|\+|=|\"|:|;|,|\{|\}|\[|\]|||].).)$`, Must not be blank, Size must be between 1 and 512 inclusive]

vendor

String

Vendor of server discovered by Network agent

[Must not be null, Possible values: [APACHE_2, IIS, TOMCAT, F5_BIG_IP]]

connectionType

String

Connection type to server discovered by Network agent

[Possible values: [LOCAL, LOCAL_LEGACY_NATIVE_API, REMOTE_REST_API, REMOTE_SSH, REMOTE_WIN_RM, REMOTE_LEGACY_NATIVE_API], vendor related.]

ip

String

Hostname or IP address of server that’s creating as one discovered by Network agent

[Maximum length is 255 characters or can be empty, Required for a remote server.]

port

Number

Port number on server discovered by Network agent

[Must be at least 0, Required for a remote server and for all except 'IIS' vendors.]

path

String

Path to root directory(in case of 'TOMCAT' vendor) or to the 'apachectl' executable(in case of 'APACHE_2' vendor) of server discovered by Network agent.

[Maximum length is 512 characters or can be empty, Can be specified for 'APACHE_2' and 'TOMCAT' vendors only. Optional.]

altPathForCert

String

Alternative path to a directory where server discovered by Network agent stores certificates.

[Can be specified for a remote server and for 'APACHE_2' vendor only. Optional.]

privateKeyPath

String

Path to a directory where Network agent stores private key to authenticate on discovered server.

[Maximum length is 128 characters or can be empty, Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'passPhrase' but not with 'username'/'password' parameters. Optional.]

passPhrase

String

Passphrase to gain access to keystore where Network agent preserves the private key to authenticate on discovered server.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Used together with 'privateKeyPath' but not with 'username' parameter. Optional.]

username

String

Username(login) to gain access to server discovered by Network agent.

[Maximum length is 64 characters or can be empty, Can be specified for a remote server and for all vendors. Must be used in conjunction with 'password' but not with 'privateKeyPath'/'passPhrase' parameters. Optional.]

password

String

Password for username to gain access to server discovered by Network agent.

[Can be specified for a remote server and for all vendors. Used together with 'username' but not with 'privateKeyPath' parameter. Optional.]

storeName

String

Store name to gain access to server discovered by Network agent.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'storeCredId' but not with 'username'/'password' parameters and not with 'privateKeyPath'/'passPhrase' parameters. Optional.]

storeCredId

String

Store credential ID to gain access to server discovered by Network agent.

[Can be specified for a remote server and for 'APACHE_2' and 'TOMCAT' vendors only. Must be used in conjunction with 'storeName' but not with 'username'/'password' parameters and not with 'privateKeyPath'/'passPhrase' parameters. Optional.]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/116/server/98' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick-1809' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1808' \
+    -d '{"name":"NetworkAgent-1","vendor":"TOMCAT","connectionType":"LOCAL_LEGACY_NATIVE_API","path":"C:\\Windows\\System32\\inetsrv","username":"SomeUser","password":"S0meYserPwB"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete server

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{id}
ParameterDescription

agentId

ID(89) of existed Network agent to delete its discovered server. Must be zero or positive integer.

id

ID(74) of existed server discovered by Network agent to delete. Must be zero or positive integer.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/89/server/74' -i -X DELETE \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1785' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1784'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+

View server nodes

+
+

List server nodes

+
+

List all nodes that match the requested filter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{serverId}/node
ParameterDescription

agentId

ID(113) of existed Network agent to get count of its discovered servers.

serverId

ID(77) of existed server discovered by Network agent to get a total count of its nodes with using filtering.Must be zero or positive integer.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

position

The start position (offset) to get a sub-list (page) of nodes in server discovered by Network agent. Optional.

size

The max count (page size) of nodes in server discovered by Network agent to be returned in sub-list (page) starting from 'position'. Max value = 200. Optional.

alias

The whole or part of name of node in server discovered by Network agent to match against to anywhere in the node name with insensitive case compare when counting. Optional.

name

The whole or part of full name of node in server discovered by Network agent to match against to anywhere in the node full name with insensitive case compare when counting. Optional.

protocol

To match against a Schema of protocol used to connect to node in server discovered by Network agent. Possible values: [HTTP, HTTPS, UNKNOWN]

address

To match against an IP address of node in server discovered by Network agent

port

To match against a Port number listening by node in server discovered by Network agent

sslId

To match against an ID of entity of SSL certificate installed on server node and discovered by Network agent either from SSL connection or from server configuration

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/113/server/77/node?size=200&position=0&name=full&alias=%201&protocol=HTTP&address=192.168.2.1' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1800' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1799'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered nodes in server discovered by Network agent.

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of nodes in the specified server discovered by Network agent according to filter request parameters.

[].id

Number

ID of node in server discovered by Network agent

[].name

String

Name of node in server discovered by Network agent

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 5
+Content-Type: application/json;charset=UTF-8
+Content-Length: 215
+
+[{"id":93,"name":"DiscoveredServerNode 19"},{"id":90,"name":"DiscoveredServerNode 16"},{"id":87,"name":"DiscoveredServerNode 13"},{"id":84,"name":"DiscoveredServerNode 10"},{"id":75,"name":"DiscoveredServerNode 1"}]
+
+
+
+
+
+

Count server nodes

+
+

Count all Network Agents that match the requested filter.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{serverId}/node
ParameterDescription

agentId

ID(83) of existed Network agent to get count of its discovered servers.

serverId

ID(52) of existed server discovered by Network agent to get a total count of its nodes with using filtering.Must be zero or positive integer.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

countOnly

Denotes that expecting a total count only to be returned in 'X-Total-Count' response header, without return a really data in response body. Required with value =true.

alias

The whole or part of name of node in server discovered by Network agent to match against to anywhere in the node name with insensitive case compare when counting. Optional.

name

The whole or part of full name of node in server discovered by Network agent to match against to anywhere in the node full name with insensitive case compare when counting. Optional.

protocol

To match against a Schema of protocol used to connect to node in server discovered by Network agent. Possible values: [HTTP, HTTPS, UNKNOWN]

address

To match against an IP address of node in server discovered by Network agent

port

To match against a Port number listening by node in server discovered by Network agent

sslId

To match against an ID of entity of SSL certificate installed on server node and discovered by Network agent either from SSL connection or from server configuration

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/83/server/52/node?countOnly=true&name=full&alias=%201&protocol=HTTP&address=192.168.2.1' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1767' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1766'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered nodes in server discovered by Network agent.

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 5
+
+
+
+
+
+

Get server node details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + + + + + +
Table 1. /api/agent/v1/network/{agentId}/server/{serverId}/node/{id}
ParameterDescription

agentId

ID(92) of existed Network agent to get details of its discovered server. Must be zero or positive integer.

serverId

ID(76) of existed server discovered by Network agent to get a few more details of its node. Must be zero or positive integer.

id

ID(74) of existed node in server discovered by Network agent to get a few more its details. Must be zero or positive integer.

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/network/92/server/76/node/74' -i -X GET \
+    -H 'Content-Type: */*;charset=UTF-8' \
+    -H 'login: nick-1794' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst1793'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

ID of node in server discovered by Network agent

alias

String

Name of node in server discovered by Network agent

name

String

Full name of node in server discovered by Network agent

protocol

String

Schema of protocol used to connect to node in server discovered by Network agent. Possible values: [HTTP, HTTPS, UNKNOWN]

address

String

IP address of node in server discovered by Network agent

port

Number

Port number listening by node in server discovered by Network agent

errorMessage

String

The error occurred when Network agent was executing a command intended for node in server discovered by Network agent

sslId

Number

ID of entity of SSL certificate installed on server node and discovered by Network agent either from SSL connection or from server configuration

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 173
+
+{"id":74,"alias":"DiscoveredServerNode 1","name":"SomeFullName","protocol":"HTTP","address":"192.168.2.1","port":8091,"errorMessage":"Some 1 error(s) occurred.","sslId":207}
+
+
+
+
+
+
+
+
+

MS Agents

+
+
+

Used to perform operations on MS Agents.

+
+
+

View MS Agents

+
+

List MS Agents

+
+

List all MS Agents that match the requested filter.

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Filter by Agent name

active

Filter by active

status

Filter by status. Allowed values: [NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

version

Filter by Agent version

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/ms?position=0&size=10' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1820' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered MS Agents

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

Number

MS Agent ID

[].name

String

MS Agent name

[].active

Boolean

MS Agent active state

[].version

String

MS Agent version

[].status

String

MS Agent current status

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 1
+Content-Type: application/json
+Content-Length: 109
+
+[{"id":87,"name":"853677a7-4524-4e22-93de-852984813a07","active":true,"version":"3.11","status":"CONNECTED"}]
+
+
+
+
+
+

Get MS Agent details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/ms/{id}
ParameterDescription

id

MS Agent ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/ms/86' -i -X GET \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1817' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

MS Agent ID

name

String

MS Agent name

active

Boolean

MS Agent active state

version

String

MS Agent version

status

String

MS Agent current status

comments

String

MS Agent comments

installationToken

String

The token which can be used during MS Agent installation

secretKey

String

MS Agent secret key

autoUpdate

Boolean

Enabled or disabled MS Agent auto update

localIp

String

IP addresses list Agent installed on

lastActivity

String

Last Agent activity timestamp

caProxyEnabled

Boolean

Is MS Agent installed as MS CA or not

adDomainsListRestricted

Boolean

If true domains from list will be excluded from discovery. If false - only specified domains will be included to discovery

adDomainsList

String

List of domains to include or exclude from discovery

defaultEnrollmentOrgId

Number

Default Organization/Department to enroll certificates by MS Agent

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 361
+
+{"installationToken":"token","id":86,"name":"4b626ce4-29ea-4d84-8a96-551db3375a4e","active":true,"version":"3.11","status":"CONNECTED","secretKey":"testsecretkey","comments":"","autoUpdate":true,"localIp":"10.10.10.10","lastActivity":"2025-08-15T09:10:29Z","caProxyEnabled":false,"adDomainsList":"","adDomainsListRestricted":false,"defaultEnrollmentOrgId":1070}
+
+
+
+
+
+
+

Manage MS Agents

+
+

Add MS Agent

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

MS Agent name

[Must not be blank, Maximum length is 128 characters or can be empty]

comments

String

MS Agent comments

[Maximum length is 256 characters or can be empty]

active

Boolean

MS Agent active state

[]

adDomainsListRestricted

Boolean

If true domains from list will be excluded from discovery. If false - only specified domains will be included to discovery

[]

adDomainsList

String

List of domains to include or exclude from discovery. Comma separated

[Maximum length is 1024 characters or can be empty]

defaultEnrollmentOrgId

Number

Default Organization/Department to enroll certificates by MS Agent

[Must be at least 1]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/ms/' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1811' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"Agent name","comments":"Comments","active":true,"adDomainsList":"ad\\domain, ad\\otherdomain","adDomainsListRestricted":false,"defaultEnrollmentOrgId":123}'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

installationToken

String

The token which can be used during MS Agent installation

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/agent/v1/ms/84
+Content-Type: application/json
+Content-Length: 29
+
+{"installationToken":"token"}
+
+
+
+
+
+

Update MS Agent details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/ms/{id}
ParameterDescription

id

MS Agent ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

MS Agent name

[Must be null or not blank, Maximum length is 128 characters or can be empty]

comments

String

MS Agent comments

[Maximum length is 256 characters or can be empty]

active

Boolean

MS Agent active state

[]

adDomainsListRestricted

Boolean

If true domains from list will be excluded from discovery. If false - only specified domains will be included to discovery

[]

adDomainsList

String

List of domains to include or exclude from discovery. Comma separated

[Maximum length is 1024 characters or can be empty]

defaultEnrollmentOrgId

Number

Default Organization/Department to enroll certificates by MS Agent

[Must be at least 1]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/ms/88' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1823' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"Agent name","comments":"Comments","active":true,"adDomainsList":"ad\\domain, ad\\otherdomain","adDomainsListRestricted":false,"defaultEnrollmentOrgId":123}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Delete MS Agent

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/agent/v1/ms/{id}
ParameterDescription

id

MS Agent ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/agent/v1/ms/85' -i -X DELETE \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer1814' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+
+
+
+

DNS Connectors

+
+
+

View DNS Connector

+
+

List DNS Connectors

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

Position shift

name

Filter by Connector name (contains)

status

Filter by status

orgIds

Filter by organization ID (comma separated)

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/connector/v1/dns?position=0&size=2&name=test&status=CONNECTED&orgIds=1%2C1079' -i -X GET \
+    -H 'login: admin_customer1829' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

String

Connector ID

[].name

String

Connector name

[].comments

String

Connector comments

[].version

String

Connector version

[].revision

String

Connector revision

[].hostname

String

Connector hostname

[].status

String

Connector current status. Possible values:[NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

[].os

String

Connector os

[].delegationMode

String

Connector delegationMode. Possible values:[GLOBAL_FOR_CUSTOMER, CUSTOMIZED]

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 3
+Content-Type: application/json;charset=UTF-8
+Content-Length: 584
+
+[ {
+  "name" : "test 855e82a1a42047349e6b2cf519549fb5",
+  "comments" : "test connector",
+  "id" : "855e82a1a42047349e6b2cf519549fb5",
+  "version" : "1.0",
+  "revision" : "aabbccee",
+  "hostname" : "localhost",
+  "os" : "Windows",
+  "status" : "CONNECTED",
+  "delegationMode" : "CUSTOMIZED"
+}, {
+  "name" : "test acf1ff538cac407eb631af0c2c6cb9e0",
+  "comments" : "test connector",
+  "id" : "acf1ff538cac407eb631af0c2c6cb9e0",
+  "version" : "1.0",
+  "revision" : "aabbccee",
+  "hostname" : "localhost",
+  "os" : "Windows",
+  "status" : "CONNECTED",
+  "delegationMode" : "CUSTOMIZED"
+} ]
+
+
+
+
+
+

Get DNS Connector details

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/connector/v1/dns/{id}
ParameterDescription

id

Connector ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/connector/v1/dns/ec209ef034c44f54896a65f59f1f00f9' -i -X GET \
+    -H 'login: admin_customer1826' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

String

Connector ID

name

String

Connector name

comments

String

Connector comments

version

String

Connector version

revision

String

Connector revision

hostname

String

Connector hostname

status

String

Connector current status. Possible values:[NOT_AVAILABLE, NOT_CONNECTED, CONNECTED]

os

String

Connector os

delegationMode

String

Connector delegationMode. Possible values:[GLOBAL_FOR_CUSTOMER, CUSTOMIZED]

delegatedOrganizations

Array

Connector delegated organizations ID and name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 370
+
+{
+  "name" : "test ec209ef034c44f54896a65f59f1f00f9",
+  "comments" : "test connector",
+  "id" : "ec209ef034c44f54896a65f59f1f00f9",
+  "version" : "1.0",
+  "revision" : "aabbccee",
+  "hostname" : "localhost",
+  "os" : "Windows",
+  "status" : "CONNECTED",
+  "delegationMode" : "CUSTOMIZED",
+  "delegatedOrganizations" : [ {
+    "id" : 1076,
+    "name" : "org4Test"
+  } ]
+}
+
+
+
+
+
+

List DNS Connector’s providers

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/connector/v1/dns/{id}/provider
ParameterDescription

id

Connector ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/connector/v1/dns/7fbd4c61c6ac4989b8643efff1808dbb/provider' -i -X GET \
+    -H 'login: admin_customer1832' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -H 'Accept: application/json'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of providers

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json;charset=UTF-8
+Content-Length: 23
+
+[ "ovh", "cloudflare" ]
+
+
+
+
+
+
+
+
+

Azure Key Vault Accounts

+
+
+

Manage Azure Key Vault resources.

+
+
+

Create Azure Key Vault account

+
+

Request fields

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Azure account name

[Must not be null, Size must be between 1 and 128 inclusive]

applicationId

String

Azure application ID

[Must not be null, Size must be between 1 and 36 inclusive]

directoryId

String

Azure directory ID

[Must not be null, Size must be between 1 and 36 inclusive]

environment

String

Azure environment. Values: [AZURE, AZURE_US_GOVERNMENT, AZURE_GERMANY, AZURE_CHINA]

[]

applicationSecret

String

Azure application (client) secret

[Must not be null, Size must be between 1 and 40 inclusive]

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts' -i -X POST \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21166' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d ' {
+   "name": "Azure Account",
+   "directoryId": "tenantId",
+   "applicationId": "applicationId",
+   "applicationSecret": "secret",
+   "environment": "AZURE"
+ }
+'
+
+
+
+
+

Response headers

+ ++++ + + + + + + + + + + + + +
NameDescription

Location

URL location of created Azure account

+
+
+

Example response

+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/azure/v1/accounts/42
+
+
+
+
+
+

Update Azure Key Vault account

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}
ParameterDescription

accountId

Azure account ID

+
+
+

Request fields

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Azure account name

[Maximum length is 128 characters or can be empty]

applicationId

String

Azure application ID

[Maximum length is 36 characters or can be empty]

directoryId

String

Azure directory ID

[Maximum length is 36 characters or can be empty]

environment

String

Azure environment. Values: [AZURE, AZURE_US_GOVERNMENT, AZURE_GERMANY, AZURE_CHINA]

[]

applicationSecret

String

Azure application (client) secret

[Size must be between 1 and 40 inclusive]

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42' -i -X PUT \
+    -H 'Content-Type: application/json;charset=utf-8' \
+    -H 'login: admin_customer21190' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"Azure Account","applicationId":"applicationId","directoryId":"tenantId","environment":"AZURE","applicationSecret":"applicationSecret"}'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+
+
+
+
+
+

Get Azure Key Vault account details

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}
ParameterDescription

accountId

Azure account ID

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42' -i -X GET \
+    -H 'login: admin_customer21178' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

delegationMode

String

Delegation mode

name

String

Azure account name

applicationId

String

Azure application ID

directoryId

String

Azure directory ID

environment

String

Azure environment

orgDelegations

Array

Delegated organization IDs

+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 159
+
+{"name":"Azure Account","applicationId":"applicationId","directoryId":"tenantId","environment":"AZURE","delegationMode":"CUSTOMIZED","orgDelegations":[100500]}
+
+
+
+
+
+

Delegate organizations to existing Azure Key Vault account

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}/delegations
ParameterDescription

accountId

Azure account ID

+
+
+

Request fields

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

delegationMode

String

Allowed values: [GLOBAL_FOR_CUSTOMER, CUSTOMIZED]

[Must not be null]

orgDelegations

Array

Delegated organization IDs. Will be ignored for GLOBAL_FOR_CUSTOMER delegation mode

[]

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42/delegations' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer21172' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"delegationMode": "CUSTOMIZED", "orgDelegations": [100500]}'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 27
+
+{"orgDelegations":[100500]}
+
+
+
+
+
+

Delete Azure Key Vault account

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}
ParameterDescription

accountId

Azure account ID

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42' -i -X DELETE \
+    -H 'login: admin_customer21175' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Check Azure Key Vault account configuration

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}/check
ParameterDescription

accountId

Azure account ID

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42/check' -i -X GET \
+    -H 'login: admin_customer21163' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].checkName

String

Name of the account configuration to be checked

[].message

String

Account check result message

+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 101
+
+[{"checkName":"Intune SCEP","message":"success"},{"checkName":"Azure Key Vault","message":"success"}]
+
+
+
+
+
+

List Azure Key Vault accounts

+
+

Query parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

size

Number of returned entries

position

the first position (entry) to return from the results of the query

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts?position=0&size=10' -i -X GET \
+    -H 'login: admin_customer21181' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 254
+
+[{"name":"Azure Account","applicationId":"applicationId","directoryId":"tenantId","id":42,"delegationMode":"CUSTOMIZED"},{"name":"Azure Account Custom","applicationId":"applicationId2","directoryId":"tenantId2","id":100500,"delegationMode":"CUSTOMIZED"}]
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].id

Number

Azure account ID

[].delegationMode

String

Delegation mode

[].name

String

Azure account name

[].applicationId

String

Azure application ID

[].directoryId

String

Azure directory ID

+
+
+

Response headers

+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of Azure accounts

+
+
+
+

List Azure Key Vault resource groups

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}/resource-groups
ParameterDescription

accountId

Azure account ID

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42/resource-groups' -i -X GET \
+    -H 'login: admin_customer21184' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 199
+
+[{"name":"name1","key":"key1","skuName":"","subscriptionId":"25da10ca-2f90-4ba0-a3e1-66a6da80309b"},{"name":"name2","key":"key2","skuName":"","subscriptionId":"6781b3dc-37e5-41bb-b29a-532f3cad6610"}]
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].key

String

Azure resource group key

[].name

String

Azure resource group name

[].skuName

String

Azure resource group SKU name

[].subscriptionId

String

Azure resource group subscription ID

+
+
+
+

List Azure Key Vaults

+
+

Path parameters

+ + ++++ + + + + + + + + + + + + + + + + + + + + +
Table 1. /api/azure/v1/accounts/{accountId}/subscriptions/{subscriptionId}/resource-groups/{resourceGroups}/vaults
ParameterDescription

accountId

Azure account ID

subscriptionId

Azure subscriptionId ID

resourceGroups

Azure resource group name

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/azure/v1/accounts/42/subscriptions/68791814-d9ea-4687-97de-a9b29560259a/resource-groups/ResourceGroupName/vaults' -i -X GET \
+    -H 'login: admin_customer21187' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 293
+
+[{"name":"name1-kv","key":"subscriptions/68791814-d9ea-4687-97de-a9b29560259a/resource-groups/ResourceGroupName/vaults/name1-kv","skuName":"PREMIUM"},{"name":"name2-kv","key":"subscriptions/68791814-d9ea-4687-97de-a9b29560259a/resource-groups/ResourceGroupName/name2-kv","skuName":"STANDARD"}]
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[].key

String

Azure vault key

[].name

String

Azure vault name

[].skuName

String

Azure vault SKU name

+
+
+
+
+
+

Enrollment Endpoints

+
+
+

Management of Enrollment endpoints, Delegations and Endpoint accounts.

+
+
+

Endpoints of any type can be viewed. Delegations management is supported for any endpoint type where applicable. +Following endpoints and accounts only can be created, updated and deleted:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription

SSL_WEB_FORM

SSL certificates Web Forms

SMIME_WEB_FORM

Client certifictes (S/MIME) Web Forms

DEVICE_WEB_FORM

Device certificates Web Forms

CODE_SIGN_WEB_FORM

Code Sign certificates Web Forms

+
+

View enrollment endpoints

+
+

List enrollment endpoints

+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

size

Count of entries

position

the first position (entry) to return from the results of the query

name

Name of the endpoint

uriExtension

URI extension

endpointTypes[]

Endpoint types, allowed values: [SSL_WEB_FORM, SMIME_WEB_FORM, DEVICE_WEB_FORM, CODE_SIGN_WEB_FORM, BULK_ENROLLMENT_WEB_FORM, PUBLIC_ACME, PRIVATE_ACME, SMIME_SCEP, DEVICE_SCEP, SMIME_SCEP_INTUNE, DEVICE_SCEP_INTUNE, SSL_EST, SMIME_EST, DEVICE_EST, SSL_REST_API, CLIENT_REST_API, DEVICE_REST_API, CODE_SIGN_REST_API]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1?size=10&position=0&name=Best&uriExtension=my-own-wf&endpointTypes%5B%5D=SSL_WEB_FORM&endpointTypes%5B%5D=SMIME_WEB_FORM' -i -X GET \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered Enrollment endpoints existing in the system

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Enrollment endpoints

[].id

Number

Endpoint ID

[].name

String

Endpoint name

[].type

String

Endpoint type

[].delegationMode

String

Delegation mode

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 201
+
+[{"id":198,"name":"Best-test SMIME_WEB_FORM569","type":"SMIME_WEB_FORM","delegationMode":"CUSTOMIZED"},{"id":197,"name":"Best-test SSL_WEB_FORM568","type":"SSL_WEB_FORM","delegationMode":"CUSTOMIZED"}]
+
+
+
+
+
+

Get details of enrollment endpoint

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{id}
ParameterDescription

id

Enrollment endpoint ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/195' -i -X GET \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

id

Number

Endpoint ID

name

String

Endpoint name

type

String

Endpoint type

delegationMode

String

Delegation mode

url

String

Endpoint URL

uriExtension

String

Endpoint URI extension

webFormAuthTypes

Array

Web Form authentication methods. IDP is available for any supported endpoint type except CODE_SIGN_WEB_FORM and SECRET_ID is available for SMIME_WEB_FORM only

organizations

Array

Delegated organizations

organizations.[].id

Number

Organization ID

organizations.[].name

String

Organization name

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 318
+
+{"id":195,"name":"Best-test SSL_WEB_FORM566","type":"SSL_WEB_FORM","delegationMode":"CUSTOMIZED","url":"https://cert-manager.com/customer/test/ssl/my-own-wf-195","uriExtension":"my-own-wf-195","organizations":[{"id":433,"name":"department4Test"},{"id":431,"name":"org4Test"}],"webFormAuthTypes":["EMAIL_CONFIRMATION"]}
+
+
+
+
+
+
+

Get config by endpoint id

+
+

Get Enrollment Endpoint config by Enrollment Endpoint id

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/168/config' -i -X GET \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+

HTTP request

+
+
+
GET /api/endpoint/v1/168/config HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+login: nick
+password: Password123!
+customerUri: test
+Host: cert-manager.com
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 378
+
+{"enrollmentHelp":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis quam mauris. Morbi dui mi, viverra vel dictum eget, portitor a risus. Pellentesque nec tellus fermentum, vulputate augue sit amet.","enrollmentLinkAddress":"https://it-msp.com/support","contactName":"Andrey Leonidas","contactEmail":"andrey.leonidas@it-msp.com","contactPhone":"+1 613 889 0008"}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

enrollmentHelp

String

Enrollment endpoint help instructions

enrollmentLinkAddress

String

Enrollment endpoint support URL

enrollmentLinkName

String

Enrollment endpoint support URL label text

webFormAuthTypes

String

Enrollment endpoint authentication types. Possible values: [EMAIL_CONFIRMATION, IDP, SECRET_ID]

contactName

String

Enrollment endpoint responsive person name

contactEmail

String

Enrollment endpoint responsive person e-mail

contactPhone

String

Enrollment endpoint responsive person phone number

+
+
+
+

Manage enrollment endpoints

+
+

Create enrollment endpoint

+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Endpoint name

[Must not be blank, Size must be between 1 and 256 inclusive]

endpointType

String

Endpoint type

[Must not be null, Allowed values: [SSL_WEB_FORM, SMIME_WEB_FORM, DEVICE_WEB_FORM, CODE_SIGN_WEB_FORM]]

uriExtension

String

Endpoint URI extension

[Must not be blank, Size must be between 1 and 58 inclusive]

config

Object

Endpoint configuration

[Must not be null]

config.enrollmentHelp

String

Endpoint enrollment instructions

[Maximum length is 2048 characters or can be empty]

config.enrollmentLinkName

String

Endpoint enrollment external instructions URL name

[Maximum length is 1024 characters or can be empty]

config.enrollmentLinkAddress

String

Endpoint enrollment external instructions URL

[Must match the regular expression (?!.\S)|((https?|ftps?|gopher|telnet|nntp)://)|(0-9A-Fa-f{2}|[-()_.!~';/?:@&=$,A-Za-z0-9]))([).!';/?:,])?$, Maximum length is 2048 characters or can be empty]

config.webFormAuthTypes[]

Array

Web Form authentication methods. IDP is available for any supported endpoint type except CODE_SIGN_WEB_FORM and SECRET_ID is available for SMIME_WEB_FORM only

[Allowed values: [EMAIL_CONFIRMATION, IDP, SECRET_ID]]

orgDelegations

Array

Delegated organizations IDs. Non-delegated endpoint is available for all organizations. Can be managed any time later via delegations resource

[Must be null or not empty]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"SSL Form Endpoint","endpointType":"SSL_WEB_FORM","uriExtension":"ssl-wf","config":{"enrollmentHelp":"Please contact support for enrollment help.","enrollmentLinkName":"Additional information","enrollmentLinkAddress":"https://example.com/additional-information","webFormAuthTypes":["EMAIL_CONFIRMATION","IDP"]},"orgDelegations":[407,409]}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

New endpoint location

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/endpoint/v1/183
+
+
+
+
+
+

Update enrollment endpoint

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{id}
ParameterDescription

id

Enrollment endpoint ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Endpoint name

[Must be null or not blank, Size must be between 1 and 256 inclusive]

config

Object

Endpoint configuration

[]

config.enrollmentHelp

String

Endpoint enrollment instructions

[Maximum length is 2048 characters or can be empty]

config.enrollmentLinkName

String

Endpoint enrollment external instructions URL name

[Maximum length is 1024 characters or can be empty]

config.enrollmentLinkAddress

String

Endpoint enrollment external instructions URL

[Must match the regular expression (?!.\S)|((https?|ftps?|gopher|telnet|nntp)://)|(0-9A-Fa-f{2}|[-()_.!~';/?:@&=$,A-Za-z0-9]))([).!';/?:,])?$, Maximum length is 2048 characters or can be empty]

config.webFormAuthTypes[]

Array

Web Form authentication methods. IDP is available for any supported endpoint type except CODE_SIGN_WEB_FORM and SECRET_ID is available for SMIME_WEB_FORM only

[Must be null or not empty, Allowed values: [EMAIL_CONFIRMATION, IDP, SECRET_ID]]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/212' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '{"name":"SSL Form Updated Endpoint","config":{"enrollmentHelp":"Please contact support for enrollment help.","enrollmentLinkName":"Additional information","enrollmentLinkAddress":"https://example.com/additional-information","webFormAuthTypes":["EMAIL_CONFIRMATION","IDP"]}}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Update config by endpoint id

+
+

Update Enrollment Endpoint config by Enrollment Endpoint id

+
+
+

Example request

+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/200/config' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '            {
+            "enrollmentHelp":"Please contact support in case of issues.",
+            "enrollmentLinkAddress":"https://support.global/requests",
+            "contactName":"Global Support",
+            "contactEmail":"global.support@support.global",
+            "contactPhone":"+10050042"
+            }
+'
+
+
+
+
+

HTTP request

+
+
+
PUT /api/endpoint/v1/200/config HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+login: nick
+password: Password123!
+customerUri: test
+Content-Length: 316
+Host: cert-manager.com
+
+            {
+            "enrollmentHelp":"Please contact support in case of issues.",
+            "enrollmentLinkAddress":"https://support.global/requests",
+            "contactName":"Global Support",
+            "contactEmail":"global.support@support.global",
+            "contactPhone":"+10050042"
+            }
+
+
+
+
+

Example response

+
+
+
HTTP/1.1 200 OK
+
+
+
+
+

Request fields

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

enrollmentHelp

String

Enrollment endpoint help instructions

[Maximum length is 2048 characters or can be empty]

enrollmentLinkAddress

String

Enrollment endpoint support URL

[Must match the regular expression (?!.\S)|((https?|ftps?|gopher|telnet|nntp)://)|(0-9A-Fa-f{2}|[-()_.!~';/?:@&=$,A-Za-z0-9]))([).!';/?:,])?$, Maximum length is 2048 characters or can be empty]

enrollmentLinkName

String

Enrollment endpoint support URL label text

[Maximum length is 1024 characters or can be empty]

webFormAuthTypes

String

Enrollment endpoint authentication types. Possible values: [EMAIL_CONFIRMATION, IDP, SECRET_ID]

[Must be null or not empty]

contactName

String

Enrollment endpoint responsive person name

[Maximum length is 1024 characters or can be empty]

contactEmail

String

Enrollment endpoint responsive person e-mail

[Maximum length is 1024 characters or can be empty]

contactPhone

String

Enrollment endpoint responsive person phone number

[Maximum length is 32 characters or can be empty]

+
+
+

Delete enrollment endpoint

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{id}
ParameterDescription

id

Enrollment endpoint ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/190' -i -X DELETE \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Delegate enrollment endpoint

+
+

Create or update enrollment endpoint delegations

+
+

Subsequent requests add new delegations, existing delegations are not removed.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{id}/delegations
ParameterDescription

id

Enrollment endpoint ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

[]

Array

Delegated organization IDs

Positive integer values

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/178/delegations' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test' \
+    -d '[396,398]'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete enrollment endpoint delegations

+
+

Allowed only for MRAO role admins. Remove all delegations. The endpoint will be available for all existing organizations.

+
+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{id}/delegations
ParameterDescription

id

Enrollment endpoint ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/188/delegations' -i -X DELETE \
+    -H 'login: nick' \
+    -H 'password: Password123!' \
+    -H 'customerUri: test'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+

Endpoint Accounts

+
+

List endpoint accounts

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{eeid}/account
ParameterDescription

eeid

Enrollment endpoint ID

+
+
+
Query parameters
+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

size

Count of entries

position

the first position (entry) to return from the results of the query

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/163/account?size=10&position=0' -i -X GET \
+    -H 'login: admin_customer514' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst514'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

X-Total-Count

Total count of filtered Endpoint accounts existing in the system

+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

[]

Array

List of Endpoint accounts

[].id

Number

Account ID

[].name

String

Account name

[].type

String

Endpoint type

[].organization

Object

Account organization

[].organization.id

Number

Organization ID

[].organization.name

String

Organization name

[].organization.department

Object

Account organization department

[].organization.department.id

Number

Organization department ID

[].organization.department.name

String

Organization department name

[].idToken

String

Account ID token

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+X-Total-Count: 2
+Content-Type: application/json
+Content-Length: 358
+
+[{"id":14,"name":"My account 2","type":"SSL_WEB_FORM","idToken":"eyJpZCI6MTQsInR5cGUiOiJTU0xfV0VCX0ZPUk0ifQ==","organization":{"id":351,"name":"org4Test"}},{"id":13,"name":"My account","type":"SSL_WEB_FORM","idToken":"eyJpZCI6MTMsInR5cGUiOiJTU0xfV0VCX0ZPUk0ifQ==","organization":{"id":352,"name":"org4Test","department":{"id":353,"name":"department4Test"}}}]
+
+
+
+
+
+

Get details of endpoint account

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{eeid}/account/{id}
ParameterDescription

eeid

Enrollment endpoint ID

id

Enrollment account ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/162/account/12' -i -X GET \
+    -H 'login: admin_customer510' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst510'
+
+
+
+
+
Response fields
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

name

String

Account name

type

String

Endpoint type

organization

Object

Account organization

organization.id

Number

Organization ID

organization.name

String

Organization name

organization.department

Object

Account organization department

organization.department.id

Number

Organization department ID

organization.department.name

String

Organization department name

idToken

String

Account ID token

profileIds

Array

Delegated profile IDs

accessCode

String

Access code

csrGenerationMethod

String

CSR Generation method

accountAuthMethod

String

Account authentication method

autoApprove

Boolean

Automatically approve requests

allowAutoRenew

Boolean

Allow auto renew

allowEmptyPin

Boolean

Allow empty PKCS12 password

preferredKeyProtectionAlgorithm

String

Preferred Key Protection Algorithm

idMappingRules[]

Array

Idp Mapping Rules

idMappingRules[].key

String

Attribute name

idMappingRules[].matchType

String

Match type

idMappingRules[].values[]

Array

Attribute values

+
+
+
Example response
+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 419
+
+{"name":"My account","type":"SSL_WEB_FORM","organization":{"id":349,"name":"org4Test","department":{"id":350,"name":"department4Test"}},"idToken":"eyJpZCI6MTIsInR5cGUiOiJTU0xfV0VCX0ZPUk0ifQ==","profileIds":[1105,1106],"accessCode":"1234","csrGenerationMethod":"BROWSER","accountAuthMethod":"ACCESS_CODE","preferredKeyProtectionAlgorithm":"AES256-SHA256","autoApprove":false,"allowAutoRenew":false,"allowEmptyPin":false}
+
+
+
+
+
+

Create endpoint account

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{eeid}/account
ParameterDescription

eeid

Enrollment endpoint ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Account name

[Must not be null, Size must be between 3 and 128 inclusive]

type

String

Endpoint type

[Must not be null, Allowed values: [SSL_WEB_FORM, SMIME_WEB_FORM, DEVICE_WEB_FORM, CODE_SIGN_WEB_FORM]]

organizationId

Number

Account organization ID

[Must not be null]

profileIds

Array

Delegated profile IDs. Only one profile ID is allowed for CODE_SIGN_WEB_FORM account type

[Must not be empty]

csrGenerationMethod

String

CSR Generation method. SERVER is available for any supported endpoint type except SSL_WEB_FORM, SECTIGOGEN is available for any except CODE_SIGN_WEB_FORM and TOKEN is available for CODE_SIGN_WEB_FORM only

[Must not be null, Allowed values: [BROWSER, SERVER, PROVIDED, SECTIGOGEN, TOKEN]]

autoApprove

Boolean

Automatically approve requests. Not applicable for SMIME_WEB_FORM and CODE_SIGN_WEB_FORM types. Must be explicitly set to 'true' for SECTIGOGEN CSR generation method

[]

allowAutoRenew

Boolean

Allow auto renew. Applicable for SSL_WEB_FORM type only

[]

allowEmptyPin

Boolean

Allow empty PKCS12 password

[]

accountAuthMethod

String

Account authentication method. Not applicable for CODE_SIGN_WEB_FORM type

[Must not be null, Allowed values: [ACCESS_CODE, IDP_ASSERTIONS_MAPPING, NONE]]

accessCode

String

Access code (mandatory and relevant for ACCESS_CODE authentication method only)

[Must be null or not blank, Maximum length is 255 characters or can be empty]

idpMappingRules

Array

IDP assertion mapping rules (mandatory and relevant for IDP_ASSERTIONS_MAPPING authentication method only)

[Must be null or not empty]

idpMappingRules[].key

String

Attribute name

[Must not be blank, Allowed values are: [cn, displayname, entitlement, eppn, givenname, groups, mail, schachomeorganization, sn, uid]]. Allowed values can vary depending on the system configuration

idpMappingRules[].matchType

String

Match type

[Must not be null, Allowed values are: [MATCHES, CONTAINS]]

idpMappingRules[].values

Array

Attribute values

[Must not be empty]

preferredKeyProtectionAlgorithm

String

Preferred key protection algorithm

[Allowed values: [AES256-SHA256, TripleDES-SHA1]]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/158/account' -i -X POST \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer492' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst492' \
+    -d '{"type":"SSL_WEB_FORM","name":"My account","type":"SSL_WEB_FORM","organizationId":334,"profileIds":[1097,1098],"csrGenerationMethod":"PROVIDED","autoApprove":true,"allowAutoRenew":true,"accountAuthMethod":"IDP_ASSERTIONS_MAPPING","idpMappingRules":[{"key":"groups","matchType":"CONTAINS","values":["admin","user"]}],"preferredKeyProtectionAlgorithm":"TripleDES-SHA1"}'
+
+
+
+
+
Response headers
+ ++++ + + + + + + + + + + + + +
NameDescription

Location

New account location

+
+
+
Example response
+
+
+
HTTP/1.1 201 Created
+Location: https://cert-manager.com/api/endpoint/v1/158/account/8
+
+
+
+
+
+

Update endpoint account

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{eeid}/account/{id}
ParameterDescription

eeid

Enrollment endpoint ID

id

Enrollment account ID

+
+
+
Request fields
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescriptionConstraints

name

String

Account name

[Size must be between 3 and 128 inclusive]

type

String

Endpoint type. Type can’t be updated once account is created

[Must not be null, Allowed values: [SSL_WEB_FORM, SMIME_WEB_FORM, DEVICE_WEB_FORM, CODE_SIGN_WEB_FORM]]

profileIds

Array

Delegated profile IDs. Only one profile ID is allowed for CODE_SIGN_WEB_FORM account type. If provided, all existing profile delegations will be replaced

[Must be null or not empty]

csrGenerationMethod

String

CSR Generation method. SERVER is available for any supported endpoint type except SSL_WEB_FORM, SECTIGOGEN is available for any except CODE_SIGN_WEB_FORM and TOKEN is available for CODE_SIGN_WEB_FORM only

[Allowed values: [BROWSER, SERVER, PROVIDED, SECTIGOGEN, TOKEN]]

autoApprove

Boolean

Automatically approve requests. Not applicable for SMIME_WEB_FORM and CODE_SIGN_WEB_FORM types. Must be explicitly set to 'true' for SECTIGOGEN CSR generation method

[]

allowAutoRenew

Boolean

Allow auto renew. Applicable for SSL_WEB_FORM type only

[]

allowEmptyPin

Boolean

Allow empty PKCS12 password

[]

accountAuthMethod

String

Account authentication method. Not applicable for CODE_SIGN_WEB_FORM type

[Allowed values: [ACCESS_CODE, IDP_ASSERTIONS_MAPPING, NONE]]

accessCode

String

Access code (mandatory and relevant for ACCESS_CODE authentication method only)

[Must be null or not blank, Maximum length is 255 characters or can be empty]

idpMappingRules

Array

IDP assertion mapping rules (mandatory and relevant for IDP_ASSERTIONS_MAPPING authentication method only). If provided, all existing rules will be replaced

[Must be null or not empty]

idpMappingRules[].key

String

Attribute name

[Must not be blank, Allowed values are: [cn, displayname, entitlement, eppn, givenname, groups, mail, schachomeorganization, sn, uid]]. Allowed values can vary depending on the system configuration

idpMappingRules[].matchType

String

Match type

[Must not be null, Allowed values are: [MATCHES, CONTAINS]]

idpMappingRules[].values

Array

Attribute values

[Must not be empty]

preferredKeyProtectionAlgorithm

String

Preferred key protection algorithm

[Allowed values: [AES256-SHA256, TripleDES-SHA1]]

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/167/account/18' -i -X PUT \
+    -H 'Content-Type: application/json;charset=UTF-8' \
+    -H 'login: admin_customer531' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst531' \
+    -d '{"type":"SSL_WEB_FORM","name":"My updated account","type":"SSL_WEB_FORM","profileIds":[1117,1118],"csrGenerationMethod":"BROWSER","autoApprove":true,"allowEmptyPin":true,"allowAutoRenew":false,"accountAuthMethod":"ACCESS_CODE","accessCode":"1234","preferredKeyProtectionAlgorithm":"TripleDES-SHA1"}'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+

Delete endpoint account

+
+
Path parameters
+ + ++++ + + + + + + + + + + + + + + + + +
Table 1. /api/endpoint/v1/{eeid}/account/{id}
ParameterDescription

eeid

Enrollment endpoint ID

id

Enrollment account ID

+
+
+
Example request
+
+
+
$ curl 'https://cert-manager.com/api/endpoint/v1/160/account/10' -i -X DELETE \
+    -H 'Content-Type: application/json' \
+    -H 'login: admin_customer501' \
+    -H 'password: Password123!' \
+    -H 'customerUri: cst501'
+
+
+
+
+
Example response
+
+
+
HTTP/1.1 204 No Content
+
+
+
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/azure-pipelines.yml new file mode 100644 index 0000000..3c79492 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-Networking-Infoblox' + +variables: + major: 1 + minor: 2 + 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.Infra-Networking-Infoblox.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.Infra-Networking-Infoblox.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/build.ps1 new file mode 100644 index 0000000..3b47185 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-Networking-Infoblox' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-Networking-Infoblox).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.nuspec new file mode 100644 index 0000000..899219a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-Networking-Infoblox + $VERSIONHERE$ + Zack Meier + Functions for Infoblox use + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psd1 new file mode 100644 index 0000000..27fe936 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psd1 @@ -0,0 +1,10 @@ +@{ + RootModule = 'ITD.Infra-Networking-Infoblox.psm1' + ModuleVersion = '' + GUID = '32fa3228-dfa3-4cc9-aac8-e14332a46abf' + Author = 'Zack Meier' + CompanyName = 'State of North Dakota' + PowerShellVersion = '5.1' + CompatiblePSEditions = 'Desktop','Core' + FunctionsToExport = @() +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psm1 new file mode 100644 index 0000000..d58fc25 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/ITD.Infra-Networking-Infoblox.psm1 @@ -0,0 +1,337 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +#> +function Get-ITDIbDNSRecord { + [CmdletBinding()] + Param + ( + [string[]] + $Hostname, + + [PSCredential] + $Credential + ) + + Begin { + If (!($Credential)) { + $Credential = Get-Credential + } + } + Process { + $result = @() + ForEach ($h in $hostname) { + $x = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host?name=$h" -ContentType "application/json" -Credential $Credential + If ($x) { + $obj = [PSCustomObject]@{ + 'HostName' = $x.ipv4addrs.Host; + 'IPv4Address' = $x.ipv4addrs.ipv4addr + 'DHCP' = $x.ipv4addrs.configure_for_dhcp + } + $result += $obj + } + } + } + End { + Write-Output $result + } +} + +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +#> +function New-ITDIbDNSRecord { + [CmdletBinding()] + Param + ( + [ipaddress] + $IPv4Address, + + [string] + $Hostname, + + [PSCredential] + $Credential + ) + + Begin { + If (!($Credential)) { + $Credential = Get-Credential + } + + $Uri = "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host" + $IPs = @([PSCustomObject]@{'ipv4addr' = $IPv4Address }) + } + Process { + $obj = [PSCustomObject]@{ + 'ipv4addrs' = $IPs; + 'name' = $Hostname; + 'view' = "default"; + } + $postJson = $obj | ConvertTo-Json + Invoke-RestMethod -Uri $Uri -Method Post -Body $postJson -ContentType "application/json" -Credential $Credential + } + End { + } +} + +function Get-IPs { + + Param + ( + [Parameter(Mandatory = $true)] + [array] + $Subnets + ) + + foreach ($subnet in $subnets) { + + #Split IP and subnet + $IP = ($Subnet -split "\/")[0] + $SubnetBits = ($Subnet -split "\/")[1] + + #Convert IP into binary + #Split IP into different octects and for each one, figure out the binary with leading zeros and add to the total + $Octets = $IP -split "\." + $IPInBinary = @() + foreach ($Octet in $Octets) { + #convert to binary + $OctetInBinary = [convert]::ToString($Octet, 2) + + #get length of binary string add leading zeros to make octet + $OctetInBinary = ("0" * (8 - ($OctetInBinary).Length) + $OctetInBinary) + + $IPInBinary = $IPInBinary + $OctetInBinary + } + $IPInBinary = $IPInBinary -join "" + + #Get network ID by subtracting subnet mask + $HostBits = 32 - $SubnetBits + $NetworkIDInBinary = $IPInBinary.Substring(0, $SubnetBits) + + #Get host ID and get the first host ID by converting all 1s into 0s + $HostIDInBinary = $IPInBinary.Substring($SubnetBits, $HostBits) + $HostIDInBinary = $HostIDInBinary -replace "1", "0" + + #Work out all the host IDs in that subnet by cycling through $i from 1 up to max $HostIDInBinary (i.e. 1s stringed up to $HostBits) + #Work out max $HostIDInBinary + $imax = [convert]::ToInt32(("1" * $HostBits), 2) - 1 + + $IPs = @() + + #Next ID is first network ID converted to decimal plus $i then converted to binary + For ($i = 1 ; $i -le $imax ; $i++) { + #Convert to decimal and add $i + $NextHostIDInDecimal = ([convert]::ToInt32($HostIDInBinary, 2) + $i) + #Convert back to binary + $NextHostIDInBinary = [convert]::ToString($NextHostIDInDecimal, 2) + #Add leading zeros + #Number of zeros to add + $NoOfZerosToAdd = $HostIDInBinary.Length - $NextHostIDInBinary.Length + $NextHostIDInBinary = ("0" * $NoOfZerosToAdd) + $NextHostIDInBinary + + #Work out next IP + #Add networkID to hostID + $NextIPInBinary = $NetworkIDInBinary + $NextHostIDInBinary + #Split into octets and separate by . then join + $IP = @() + For ($x = 1 ; $x -le 4 ; $x++) { + #Work out start character position + $StartCharNumber = ($x - 1) * 8 + #Get octet in binary + $IPOctetInBinary = $NextIPInBinary.Substring($StartCharNumber, 8) + #Convert octet into decimal + $IPOctetInDecimal = [convert]::ToInt32($IPOctetInBinary, 2) + #Add octet to IP + $IP += $IPOctetInDecimal + } + + #Separate by . + $IP = $IP -join "." + $IPs += $IP + + + } + $IPs + } +} + +<# +.SYNOPSIS + Dynamically creates DNS A records +.DESCRIPTION + Dynamically creates DNS A records based on CIDR input +.EXAMPLE + New-ITDIbDNSRecordNextAvailableIP -Hostname itdserver1.nd.gov -CIDR 10.11.12.0/23 -Credential $Credential +.EXAMPLE + New-ITDIbDNSRecordNextAvailableIP -Hostname itdserver2.nd.gov,itdserver3.nd.gov,itdserver4.nd.gov -CIDR 10.11.12.0/23 -Credential $Credential +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function New-ITDIbDNSRecordNextAvailableIP { + [CmdletBinding()] + Param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [string[]] + $Hostname, + + [Parameter(Mandatory = $true)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [ValidatePattern("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$")] + [string] + $CIDR, + + [PSCredential] + $Credential + ) + + begin { + $NetworkAddress = $CIDR.split('/')[0] + $IPs = Get-IPs -Subnets $CIDR + $ExcludeIPs = $IPs | select -First 1 + } + + process { + #$ curl -k -u admin:infoblox -X GET https://10.64.41.6/wapi/v1.1/network?ipv4addr=10.144.2.0 + try { + $networkobj = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/network?ipv4addr=$NetworkAddress" -Credential $Credential -ContentType "application/json" -ErrorAction Stop + $networkobjref = $networkobj._ref + + #curl -k -u admin:infoblox -X POST https://10.64.41.6/wapi/v1.1/network/ZG5zLm5ldHdvcmskMTAuMTQ0LjIuMC8yNC8w:10.144.2.0/24/default?_function=next_available_ip -H "Content-Type: application/json" -d '{"exclude": ["10.144.2.8", "10.144.2.10"], "num": 6}' + $bodyjson = @{num = @($Hostname).count; exclude = @($ExcludeIPs) } | ConvertTo-Json + #Invoke-RestMethod -Method Post -Uri ("https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $networkobjref + "?_function=next_available_ip") -ContentType "application/json" -Credential $Credential -Body '{"exclude": ["10.11.12.1", "10.11.12.2"], "num": 6}' #WORKS + $IPsAvailable = (Invoke-RestMethod -Method Post -Uri ("https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $networkobjref + "?_function=next_available_ip") -ContentType "application/json" -Credential $Credential -Body $bodyjson -ErrorAction Stop).Ips + + $IPCount = 0 + + ForEach ($hn in $hostname) { + if (Get-ITDIbDNSRecord -Hostname $hn -Credential $Credential) { + Write-Warning "DNS record already exists" + } + else { + New-ITDIbDNSRecord -IPv4Address $IPsAvailable[$IPCount] -Hostname $hn -Credential $Credential -ErrorAction Stop + $IPcount++ + } + } + } + catch [System.Net.WebException] { + Write-Error "webexception error" + } + } + + end { + } +} + +function Get-ITDIbVlan { + [CmdletBinding()] + Param( + [Parameter( + ParameterSetName = 'VlanLookup')] + [ValidateRange(0, 4096)] + [int[]] + $Vlan, + + [Parameter( + ParameterSetName = 'CIDRLookup')] + [string[]] + $CIDR, + + [PSCredential] + $Credential + ) + begin { + + } + process { + $Output = @() + + switch ($PsCmdlet.ParameterSetName) { + "VlanLookup" { + ForEach ($v in $Vlan) { + $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?id=$v&_return_as_object=1&_return_fields=assigned_to,id,name,parent,comment,description" -ContentType "application/json" -Credential $Credential + $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } } + $Output += $InvokePSObject + } + } + "CIDRLookup" { + ForEach ($c in $CIDR) { + $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?_return_as_object=1&_max_results=-50000&_return_fields=assigned_to,id,name,parent,comment,description" -ContentType "application/json" -Credential $Credential + $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } } + $Output += $InvokePSObject | Where-Object AssignedTo -EQ $c + } + } + "default" { + $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?_return_as_object=1&_max_results=-50000&_return_fields=assigned_to,id,name,parent,comment,description" -ContentType "application/json" -Credential $Credential + $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } } + $Output = $InvokePSObject + } + } + } + end { + Write-Output $Output + } +} + +function Remove-ITDIbDnsRecord { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [PSCredential] + $Credential + ) + + Begin { + If (!($Credential)) { + $Credential = Get-Credential + } + + + } + Process { + $DNSRecord = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host?name=$ComputerName" -ContentType "application/json" -Credential $Credential + $UriToDelete = ( "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $DNSRecord._ref ) + Invoke-RestMethod -Method Delete -Uri $UriToDelete -ContentType "application/json" -Credential $Credential + } + + end { + + } +} + + + + + + + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/README.md b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Networking-Infoblox/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/azure-pipelines.yml new file mode 100644 index 0000000..9677fec --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-Passwordstate' + +variables: + major: 0 + minor: 2 + 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.Infra-Passwordstate.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.Infra-Passwordstate.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/build.ps1 new file mode 100644 index 0000000..ee393fb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-Passwordstate' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-Passwordstate).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.nuspec new file mode 100644 index 0000000..c342877 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-Passwordstate + $VERSIONHERE$ + Zack Meier + Functions for Passwordstate use + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psd1 new file mode 100644 index 0000000..3f8d164 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psd1 @@ -0,0 +1,10 @@ +@{ + RootModule = 'ITD.Infra-Passwordstate.psm1' + ModuleVersion = '' + GUID = '3b3f771e-962a-4f67-bca6-4e5d9df870c5' + Author = 'Zack Meier' + CompanyName = 'State of North Dakota' + PowerShellVersion = '5.1' + CompatiblePSEditions = 'Desktop','Core' + FunctionsToExport = @() +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/ITD.Infra-Passwordstate.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Export-ITDPasswordList.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Export-ITDPasswordList.ps1 new file mode 100644 index 0000000..8fa2ad5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Export-ITDPasswordList.ps1 @@ -0,0 +1,52 @@ +<# +.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 Export-ITDPasswordList { + [CmdletBinding()] + param ( + [string] + $PasswordList, + + [string] + $Destination, + + [PSCredential] + $Credential + ) + + begin { + $PasswordListSearch = Get-ITDPasswordList -PasswordList $PasswordList -Credential $Credential + switch (@($PasswordListSearch).count) { + { $_ -gt 1 } { + Write-Error -Message "More than one password list found, adjust search" -ErrorAction Stop + } + { $_ -le 0} { + Write-Error -Message "Zero password lists found, adjust search" -ErrorAction Stop + } + { 1 }{ + $PasswordListId = $PasswordListSearch.PasswordListId + } + } + } + + process { + $PasswordstateUrl = ("https://itdpv.nd.gov/winapi/passwords/" + $PasswordListId + "?QueryAll&PreventAuditing=true") + $Passwords = Invoke-RestMethod -Method GET -Uri $PasswordstateUrl -Credential $Credential + $Passwords | Export-Csv -Path $Destination + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Find-ITDPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Find-ITDPassword.ps1 new file mode 100644 index 0000000..8dec4a6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Find-ITDPassword.ps1 @@ -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 Find-ITDPassword { + [CmdletBinding()] + param ( + [string] + $Title, + + [string] + $UserName, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + $Uri = 'https://itdpv.nd.gov/winapi/searchpasswords/?' + + If ($Title) { $Uri += 'title=' + $Title + '&' } + If ($UserName) { $Uri += 'username=' + "$UserName" + '&' } + $Uri = $Uri.TrimEnd('&') + + $InvokeResult = Invoke-RestMethod -Method Get -Uri $Uri -Credential $Credential -ErrorAction SilentlyContinue + + Write-Output $InvokeResult + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPassword.ps1 new file mode 100644 index 0000000..0950b97 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPassword.ps1 @@ -0,0 +1,99 @@ +<# +.SYNOPSIS + Retrive password from ITD Passwordstate +.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 -VerboseZM + Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines +#> + +function Get-ITDPassword { + [CmdletBinding()] + param ( + [string] + $Title, + + [string] + $UserName, + + [PSCredential] + $Credential, + + [Parameter(ParameterSetName = "ToClipboard")] + [switch] + $ToClipboard, + + [switch] + $FullRecord + ) + + begin { + + } + + process { + $Uri = 'https://itdpv.nd.gov/winapi/searchpasswords/?' + + If ($PSBoundParameters.ContainsKey('Title')) { + $Uri += 'title=' + $Title + '&' + } + If ($PSBoundParameters.ContainsKey('Username')) { + $Uri += 'username=' + "$UserName" + '&' + } + + $Uri = $Uri.TrimEnd('&') + + $InvokeRestMethodParams = @{ + Method = 'Get'; + Uri = $Uri; + SkipHttpErrorCheck = $true; + } + If ($PSBoundParameters.ContainsKey('Credential')) { + $InvokeRestMethodParams += @{Credential = $Credential } + } + Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true } + } + $InvokeResult = Invoke-RestMethod @InvokeRestMethodParams + + switch ($InvokeResult) { + { $_ -eq $null } { + Write-Error -Message "No password found" + Break + } + { $_ | Get-Member -MemberType Properties | Where-Object { $_.Name -eq 'errors' } } { + If ($InvokeResult.errors.message -eq 'Not found') { + Write-Warning -Message "Search for Password records return zero results" + } + } + Default { + $OutResult = $InvokeResult | Select-Object PasswordListID, PasswordList, PasswordID, Title, Description, UserName, @{n = 'SecurePassword'; e = { $_.Password | ConvertTo-SecureString -AsPlainText -Force } }, AccountTypeId, AccountType + + If (@($OutResult).count -eq 1) { + If ($PSCmdlet.ParameterSetName -eq "ToClipboard") { + $InvokeResult.Password | Set-Clipboard + } + If ($FullRecord) { + Write-Output $OutResult + } + Else { + $OutCred = New-Object System.Management.Automation.PSCredential($OutResult.UserName, $OutResult.SecurePassword) + Write-Output $OutCred + } + } + Else { + Write-Output $OutResult + } + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordAccountTypeId.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordAccountTypeId.ps1 new file mode 100644 index 0000000..b735c1a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordAccountTypeId.ps1 @@ -0,0 +1,35 @@ +<# +.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-ITDPasswordAccountTypeId { + [CmdletBinding()] + Param( + [ValidateSet('VMware ESXi','Active Directory','HP iLO')] + [string] + $AccountType + ) + Begin { + + } + Process { + switch ($AccountType) { + 'VMware ESXi' { $AccountTypeId = 34 } + 'Active Directory' { $AccountTypeId = 70 } + 'HP iLO' { $AccountTypeId = 1084 } + } + } + End { + return $AccountTypeId + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordList.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordList.ps1 new file mode 100644 index 0000000..86a91bd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Get-ITDPasswordList.ps1 @@ -0,0 +1,58 @@ +<# +.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-ITDPasswordList { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $PasswordList, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + $Uri = "https://itdpv.nd.gov/winapi/searchpasswordlists/?" + + If ($PasswordList) { $Uri += "PasswordList=$PasswordList" } + $Uri = $Uri.TrimEnd('&') + + $InvokeRestMethodParams = @{ + Method = 'Get'; + Uri = $Uri; + } + If ($PSBoundParameters.ContainsKey('Credential')){ + $InvokeRestMethodParams += @{Credential = $Credential} + } Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true} + } + + $reply = Invoke-RestMethod -Method Get -Uri $Uri -Credential $Credential + If ($PasswordList) { + $result = $reply | Where-Object PasswordList -EQ $PasswordList + } + Else { + $result = $reply + } + } + + end { + Write-Output $result + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDPassword.ps1 new file mode 100644 index 0000000..8094619 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDPassword.ps1 @@ -0,0 +1,134 @@ +<# +.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-ITDPassword { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + #[ValidateSet('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI')] + [string] + $PasswordList, + + [Parameter(Mandatory = $true)] + [string] + $Title, + + [Parameter(Mandatory = $true)] + [string] + $Description, + + [string] + $AccountType, + + [Parameter(ParameterSetName = 'GeneratePassword', Mandatory)] + [string] + $UserName, + + [string] + $Notes, + + [Parameter(ParameterSetName = 'EnterCredential')] + [PSCredential] + $CredentialToSave, + + [PSCredential] + $Credential + ) + + begin { + $PSList = Get-ITDPasswordList -PasswordList $PasswordList -Credential $Credential + If (@($PSList).count -gt 1) { Write-Error "More than one PasswordList match." -ErrorAction Stop } + } + + process { + switch ($PSCmdlet.ParameterSetName) { + 'EnterCredential' { + Write-Verbose -Message "EnterCredential" + $Username = $CredentialToSave.UserName + $Password = $CredentialToSave.GetNetworkCredential().Password + } + 'GeneratePassword' { + Write-Verbose -Message "GeneratePassword" + $Password = New-ITDRandomPassword -Credential $Credential + } + } + + Write-Verbose -Message "Create password object" + $PasswordObj = [PSCustomObject]@{ + 'PasswordListID' = $PSList.PasswordListID; + 'Title' = $Title; + 'Description' = $Description; + 'UserName' = $Username; + 'Password' = $Password; + 'Notes' = ("Auto-generated by " + $Credential.UserName + " @ " + (Get-Date -UFormat "%Y/%m/%d %H:%M:%S")); + } + + switch ($PSBoundParameters.Keys) { + Notes { + $PasswordObj.Notes += ("`n" + $Notes) + } + } + + If ($AccountType) { + $AccountTypeId = Get-ITDPasswordAccountTypeId -AccountType $AccountType + $PasswordObj | Add-Member -Name AccountTypeId -MemberType NoteProperty -Value $AccountTypeId + } + else { + $PasswordObj | Add-Member -Name AccountTypeId -MemberType NoteProperty -Value 0 + } + + $InvokeRestMethodParams = @{ + Method = 'Post'; + Uri = 'https://itdpv.nd.gov/winapi/passwords'; + ContentType = 'application/json'; + Body = ($PasswordObj | ConvertTo-Json); + } + + If ($PSBoundParameters.ContainsKey('Credential')){ + $InvokeRestMethodParams += @{Credential = $Credential} + } Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true} + } + + Write-Verbose -Message "Invoke Passwordstate record creation" + $InvokeResult = Invoke-RestMethod @InvokeRestMethodParams + + #Write-Verbose -Message "Store Invoke result in variable" + #$OutResult = $InvokeResult | Select-Object PasswordList, Title, Description, UserName, @{n = 'SecurePassword'; e = { $_.Password | ConvertTo-SecureString -AsPlainText -Force } }, AccountTypeId, AccountType + <# storing the returned PSCredential object (see code above) sometimes causes the following error: + [error] Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value." + Running Get-ITDPassword does not cause the error, unsure of cause. Unsure of the reason why, not looking into it further + #> + + + Write-Verbose -Message "Retrieve new password" + $GetITDPasswordParams = @{ + Title = $Title; + UserName = $UserName; + } + If ($PSBoundParameters.ContainsKey('Credential')){ + $GetITDPasswordParams += @{Credential = $Credential} + } Else { + $GetITDPasswordParams += @{UseDefaultCredentials = $true} + } + $OutResult = Get-ITDPassword @GetITDPasswordParams + + #Write-Verbose -Message "put OutResult in credential variable and return" + #$OutCred = New-Object System.Management.Automation.PSCredential($OutResult.UserName, $OutResult.SecurePassword) + } + + end { + Write-Output $OutResult + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDRandomPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDRandomPassword.ps1 new file mode 100644 index 0000000..94dd640 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/New-ITDRandomPassword.ps1 @@ -0,0 +1,52 @@ +<# +.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-ITDRandomPassword { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + Begin { + } + Process { + $InvokeRestMethodParams = @{ + Method = 'Get'; + Uri = 'https://itdpv.nd.gov/winapi/generatepassword/?PasswordGeneratorID=2'; + ErrorAction = 'Stop'; + } + + If ($PSBoundParameters.ContainsKey('Credential')){ + $InvokeRestMethodParams += @{Credential = $Credential} + } Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true} + } + + $NewPassword = (Invoke-RestMethod @InvokeRestMethodParams).Password + $Length = $NewPassword.Length + While ($null -ne $NewPassword -and $Length -lt 20) { + $NewPassword2 = (Invoke-RestMethod @InvokeRestMethodParams).Password + $NewPassword += $NewPassword2.split('-')[1] + $Length = $NewPassword.Length + } + If (!($NewPassword -match '\d')) { $NewPassword += (Get-Random -Minimum 0 -Maximum 9) } + } + End { + return $NewPassword + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Remove-ITDPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Remove-ITDPassword.ps1 new file mode 100644 index 0000000..c8467c2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Remove-ITDPassword.ps1 @@ -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 + 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 Remove-ITDPassword { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0, ParameterSetName = "Title")] + [ValidateNotNullOrEmpty()] + [String] + $Title, + + [switch] + $Force, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + # Find the passwords + $GetITDPasswordParams = @{ + Title = $Title; + } + If ($PSBoundParameters.ContainsKey('Credential')) { + $InvokeRestMethodParams += @{Credential = $Credential } + } + Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true } + } + + $ExistingRecords = Get-ITDPassword @GetITDPasswordParams + + switch ($ExistingRecords.count) { + { [int]0 } { + Write-Warning -Message "Title $Title not found." + } + { $_ -ge 1 } { + If (-not $Force) { + $VerifyString = ( ([string]@($ExistingRecords).Count) + " record(s) have been found, all will be removed.") + $question = 'Are you sure you want to proceed?' + + $choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription] + $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes')) + $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No')) + + $decision = $Host.UI.PromptForChoice($VerifyString, $question, $choices, 1) + } + if ($decision -eq 0 -or $Force -eq $true) { + ForEach ($ExistingRecord in $ExistingRecords) { + $Uri = ("https://itdpv.nd.gov/winapi/passwords/" + $ExistingRecord.PasswordID + "?MoveToRecycleBin=True") + + $InvokeRestMethodParams = @{ + Method = 'Delete'; + Uri = $Uri; + ContentType = 'application/json'; + } + If ($PSBoundParameters.ContainsKey('Credential')) { + $InvokeRestMethodParams += @{Credential = $Credential } + } + Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true } + } + + Invoke-RestMethod @InvokeRestMethodParams + } + } + else { + + } + } + } + + + + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Update-ITDPassword.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Update-ITDPassword.ps1 new file mode 100644 index 0000000..36e8e4a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/Public/Update-ITDPassword.ps1 @@ -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 Update-ITDPassword { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0, ParameterSetName = "Id")] + [ValidateRange(1, [UInt32]::MaxValue)] + [Int]$Id, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0, ParameterSetName = "Title")] + [ValidateNotNullOrEmpty()] + [String]$Title, + + [String] + $Notes, + + [switch] + $AppendNotes, + + [PSCredential] + $Credential, + + [switch] + $Force, + + [switch] + $All + ) + + begin { + + } + + process { + $GetITDPasswordParams = @{ + Title = $Title; + } + If ($PSBoundParameters.ContainsKey('Credential')) { + $InvokeRestMethodParams += @{Credential = $Credential } + } + Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true } + } + + $ExistingRecords = Get-ITDPassword @GetITDPasswordParams + + If (-not $Force) { + $title = ( ([string]@($ExistingRecords).Count) + " record(s) have been found, all will be modified.") + $question = 'Are you sure you want to proceed?' + + $choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription] + $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes')) + $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No')) + + $decision = $Host.UI.PromptForChoice($title, $question, $choices, 1) + } + + if ($Force -eq $true -or $decision -eq 0) { + ForEach ($ExistingRecord in $ExistingRecords) { + + $PasswordObj = @{ + 'PasswordID' = $ExistingRecord.PasswordID + } + + switch ($PSBoundParameters.Keys) { + 'Notes' { + if ($PSBoundParameters.AppendNotes) { + $PasswordObj.Notes = $ExistingRecord.Notes + "
 
$($PSBoundParameters.Notes)" + } + else { + $PasswordObj.Notes = $PSBoundParameters.Notes + } + } + } + + $InvokeRestMethodParams = @{ + Method = 'Put'; + Uri = 'https://itdpv.nd.gov/winapi/passwords'; + ContentType = 'application/json'; + Body = ($PasswordObj | ConvertTo-Json); + } + If ($PSBoundParameters.ContainsKey('Credential')) { + $InvokeRestMethodParams += @{Credential = $Credential } + } + Else { + $InvokeRestMethodParams += @{UseDefaultCredentials = $true } + } + + $InvokeRestMethodParams.Body + + Invoke-RestMethod @InvokeRestMethodParams + } + } + else { + + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/README.md b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Passwordstate/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/Get-ITDServiceNowRecord b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/Get-ITDServiceNowRecord new file mode 100644 index 0000000..07863c4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/Get-ITDServiceNowRecord @@ -0,0 +1,7 @@ +Param ( + [string] + $Number +) + + +Write-Output @{Number = $Number} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/accessControls.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/accessControls.ps1 new file mode 100644 index 0000000..8b9db8e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/accessControls.ps1 @@ -0,0 +1,17 @@ +New-PSUAccessControl -Role "Team-Windows" -Type "View, Execute" -Tag "Team-Windows_Execute" +New-PSUAccessControl -Role "Team-Windows" -Type "View, Edit, Create, Delete, Execute" -Tag "Team-Windows_Modify" +New-PSUAccessControl -Role "Team-Network" -Type "View, Execute" -Tag "Team-Network_Execute" +New-PSUAccessControl -Role "Team-Linux" -Type "View, Execute" -Tag "Team-Linux_Execute" +New-PSUAccessControl -Role "Team-ConnectND" -Type "View, Execute" -Tag "Team-CND_Execute" +New-PSUAccessControl -Role "Team-Tier2" -Type "View, Execute" -Tag "Team-Tier2_Execute" +New-PSUAccessControl -Role "Team-Mgmt" -Type "View, Execute" -Tag "Team-Mgmt_Execute" +New-PSUAccessControl -Role "Team-Mgmt" -Type "View, Edit, Create, Delete, Execute" -Tag "Team-Mgmt_Modify" +New-PSUAccessControl -Role "App-Infra-VMware" -Type "View, Execute" -Tag "Infra-VMware_Execute" +New-PSUAccessControl -Role "App-Infra-VMware" -Type "View, Edit, Create, Delete, Execute" -Tag "Infra-VMware_Modify" +New-PSUAccessControl -Role "App-ITD-WindowsServer" -Type "View, Execute" -Tag "ITD-WindowsServer_Execute" +New-PSUAccessControl -Role "App-ITD-WindowsServer" -Type "View, Edit, Create, Delete, Execute" -Tag "ITD-WindowsServer_Modify" +New-PSUAccessControl -Role "App-Shared-PowerSchool" -Type "View, Execute" -Tag "Shared-PowerSchool_Execute" +New-PSUAccessControl -Role "App-Shared-PowerSchool" -Type "View, Edit, Create, Delete, Execute" -Tag "Shared-PowerSchool_Modify" +New-PSUAccessControl -Role "Team-Collaboration" -Type "View, Execute" -Tag "Team-Collaboration_Execute" +New-PSUAccessControl -Role "Team-Collaboration" -Type "View, Edit, Create, Delete, Execute" -Tag "Team-Collaboration_Modify" +New-PSUAccessControl -Role "App-Infra-Certificate" -Type "View, Edit, Execute" -Tag "Infra-Certificate_Modify" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/authentication.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/authentication.ps1 new file mode 100644 index 0000000..6fbeba1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/authentication.ps1 @@ -0,0 +1,87 @@ +Set-PSUAuthenticationMethod -Type "Form" -ScriptBlock { +param( + [PSCredential]$Credential + ) + + Add-Type -AssemblyName System.DirectoryServices.AccountManagement + + # is this a UPN? + if ( $Credential.UserName.IndexOf('@') -gt -1 ) { + + # juggle back and forth from SID to get NTAccount format + $NTAccountName = ([System.Security.Principal.NTAccount]$Credential.UserName).Translate([System.Security.Principal.SecurityIdentifier]).Translate([System.Security.Principal.NTAccount]).Value + + } elseif ( $Credential.UserName.IndexOf('\') -gt -1 ) { + + # already NTAccount format + $NTAccountName = $Credential.UserName + + } else { + + # someone didn't enter their domain... + $NTAccountName = "NDGOV\" + $Credential.GetNetworkCredential().UserName + + } + + # split domain and username + $DomainName, $UserName = $NTAccountName.Split('\',2) + + # perform auth with AD + $PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( 'Domain', $DomainName ) + $Authenticated = $PrincipalContext.ValidateCredentials( $UserName, $Credential.GetNetworkCredential().Password, 'Negotiate, Sealing' ) + + if ( $Authenticated ) { + + # discover the user principal, needed for the user DN + $UserPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $NTAccountName ) + + # get the user's domain + $UserDomainContext = [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new( 'Domain', $DomainName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) + $UserDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain( $UserDomainContext ) + + # get the computer's domain + #$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() + + # hold all the user groups + [System.Collections.Generic.List[hashtable]]$Groups = @() + + # get groups from user's domain + #[adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName)))", @('name') ).FindAll().ForEach({ + [adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName))(name=ITD-PSUniversal-*))", @('name') ).FindAll().ForEach({ + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $UserDomain.Name + }) + }) + <# + # get groups from the computer's domain (if different) + if ( $UserDomain.Name -ne $ComputerDomain.Name ) { + + # lookup the user's foreign security principal in the computer's domain + $ForeignSecurityPrincipal = [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=foreignSecurityPrincipal)(objectClass=foreignSecurityPrincipal)(name=$($UserPrincipal.Sid)))", @('distinguishedName') ).FindOne().Properties['distinguishedName'][0] + + # find all the group memberships + [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$ForeignSecurityPrincipal))", @('name') ).FindAll().ForEach({ + + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $ComputerDomain.Name + }) + + }) + + } + #> + New-PSUAuthenticationResult -Success -UserName $UserPrincipal.UserPrincipalName -Claims { + $Groups | ForEach-Object { New-PSUAuthorizationClaim @_ } + } + + } else { + + New-PSUAuthenticationResult -ErrorMessage 'Bad username or password :)' + + } +} +Set-PSUAuthenticationMethod -Type "Windows" -Disabled \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/dashboards.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/dashboards.ps1 new file mode 100644 index 0000000..3672bda --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/dashboards.ps1 @@ -0,0 +1,6 @@ +New-PSUApp -Name "PSUVariableReview" -FilePath "dashboards\PSUVariableReview\PSUVariableReview.ps1" -BaseUrl "/PSUVariableReview" -Authenticated -AutoDeploy +New-PSUApp -Name "Infra-VMware_Snapshot" -FilePath "dashboards\Infra-VMware_Snapshot\Infra-VMware_Snapshot.ps1" -BaseUrl "/Infra-VMware_Snapshot" -Authenticated -AutoDeploy +New-PSUApp -Name "ServiceNowDumps" -FilePath "dashboards\ServiceNowDumps\ServiceNowDumps.ps1" -BaseUrl "/ServiceNowDumps" -Authenticated -AutoDeploy +New-PSUApp -Name "NewITDADServiceAccount" -FilePath "dashboards\NewITDADServiceAccount\NewITDADServiceAccount.ps1" -BaseUrl "/NewITDADServiceAccount" -Authenticated -AutoDeploy +New-PSUApp -Name "ITD-WindowsServer_FileManagement" -FilePath "dashboards\ITD-WindowsServer_FileManagement\ITD-WindowsServer_FileManagement.ps1" -BaseUrl "/ITD-WindowsServer_FileManagement" -Authenticated -AutoDeploy +New-PSUApp -Name "ServiceNow" -FilePath "dashboards\ServiceNow\ServiceNow.ps1" -BaseUrl "/ServiceNow" -Authenticated -AutoDeploy \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/endpoints.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/endpoints.ps1 new file mode 100644 index 0000000..c2a2093 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/endpoints.ps1 @@ -0,0 +1 @@ +New-PSUEndpoint -Url "/Get-ITDServiceNowRecord" -Method @('GET') -Authentication -Path "Get-ITDServiceNowRecord" -Tag @('Infra-VMware_Execute','Team-Windows_Execute','Infra-VMware_Modify','Team-Windows_Modify') \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/loginPage.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/loginPage.ps1 new file mode 100644 index 0000000..682058d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/loginPage.ps1 @@ -0,0 +1,15 @@ +$Parameters = @{ + Image = "/PSUniversal_Extras/logo.png" + Title = "PowerShell Universal" + Links = @( + New-PSULoginPageLink -Text 'ServiceNow' -Url 'https://northdakota.service-now.com/' + New-PSULoginPageLink -Text 'VMware vCenter' -Url 'https://itdvmvc1.nd.gov/ui' + New-PSULoginPageLink -Text 'Microsoft Azure' -Url 'https://portal.azure.com' + New-PSULoginPageLink -Text 'Passwordstate' -Url 'https://itdpv.nd.gov' + New-PSULoginPageLink -Text 'Solarwinds' -Url 'https://solarwinds.nd.gov/' + New-PSULoginPageLink -Text 'Panorama' -Url 'https://panorama-gov.nd.gov/php/login.php' + New-PSULoginPageLink -Text 'Ansible' -Url 'https://ansible.nd.gov/#/login' + New-PSULoginPageLink -Text 'Confluence Wiki' -Url 'https://wiki.nd.gov/i/dashboard.action' + ) +} +New-PSULoginPage @Parameters \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/publishedFolders.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/publishedFolders.ps1 new file mode 100644 index 0000000..106a53b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/publishedFolders.ps1 @@ -0,0 +1 @@ +New-PSUPublishedFolder -RequestPath "/PSUniversal_Extras" -Path "E:\PSUniversal_Extras" -Name "PSUniversal_Extras" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/roles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/roles.ps1 new file mode 100644 index 0000000..c8290ac --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/roles.ps1 @@ -0,0 +1,149 @@ +New-PSURole -Name "Administrator" -Description "Administrators can manage settings, create and edit any entity and view all the entities with PowerShell Universal." -Policy { +param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + #$false + + <# + $UserName = ($User.Identity.Name) + $UserName = $UserName.Substring($UserName.IndexOf('\') + 1, ($UserName.Length - ($UserName.IndexOf('\') + 1))) + + $IsMember = $false; + + # Perform LDAP Group Member Lookup + $Searcher = New-Object DirectoryServices.DirectorySearcher + $Searcher.SearchRoot = 'LDAP://OU=USERS, OU=ITD, DC=nd, DC=gov' # INSERT ROOT LDAP HERE + $Searcher.Filter = "(&(objectCategory=person)(memberOf=CN=ITD-PSUniversal-Admin,OU=ITDGROUPS,OU=GROUPS,OU=ITD,DC=nd,DC=gov))" #GROUP INSERT DN TO CHECK HERE + $Users = $Searcher.FindAll() + $Users | ForEach-Object { + If ($_.Properties.samaccountname -eq $UserName) { + $IsMember = $true; + "$UserName is a member of admin group!" | Out-File "C:\test\adgroup.txt" + } + else { + "$UserName is NOT member of admin group!" | Out-File "C:\test\adgroup.txt" + } + } + + return $IsMember + #> + + param($User) + + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains 'ITD-PSUniversal-Admin' +} +New-PSURole -Name "Operator" -Description "Operators have access to manage and execute scripts, create other entities within PowerShell Universal but cannot manage PowerShell Universal itself." -Policy { +param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + #$false + + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains 'ITD-PSUniversal-Operator' +} +New-PSURole -Name "Reader" -Description "Readers have read-only access to PowerShell Universal. They cannot make changes to any entity within the system." -Policy { +param( + [Security.ClaimsPrincipal] + $User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + $User | ConvertTo-Json | Set-Content ("C:\temp\user-" + $User.Identity.Name + ".json") + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -match "ITD-PSUniversal-*" +} +New-PSURole -Name "Execute" -Description "Execute scripts within PowerShell Universal." -Policy { +param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + $false +} +New-PSURole -Name "User" -Description "Does not have access to the admin console but can be assigned resources like APIs, scripts, dashboards and pages." -Policy { +param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + $false +} +New-PSURole -Name "Team-Windows" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Windows" +} +New-PSURole -Name "Team-Linux" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Linux" +} +New-PSURole -Name "Team-ConnectND" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-ConnectND" +} +New-PSURole -Name "Team-Network" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Network" +} +New-PSURole -Name "Team-Tier2" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Tier2" +} +New-PSURole -Name "Team-Mgmt" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Mgmt" +} +New-PSURole -Name "App-Infra-VMware" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Infra-VMware" +} +New-PSURole -Name "App-ITD-WindowsServer" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-ITD-WindowsServer" +} +New-PSURole -Name "App-Shared-Powerschool" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Shared-PowerSchool" +} +New-PSURole -Name "Team-Collaboration" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Collaboration" +} +New-PSURole -Name "App-Infra-Certificate" -Policy { +param($User) + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Infra-Certificate" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/schedules.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/schedules.ps1 new file mode 100644 index 0000000..024f1ff --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/schedules.ps1 @@ -0,0 +1,27 @@ +New-PSUSchedule -Cron "*/20 * * * *" -Script "Infra-VMware.Snapshot\Update-ITDVMwareVMSnapshotStatus.ps1" -TimeZone "America/Chicago" -Name "Update-ITDVMwareVMSnapshotStatus" -RandomDelay +New-PSUSchedule -Cron "* * * * *" -Script "ZM-Test\Test-ITDSchedule.ps1" -TimeZone "America/Chicago" -Credential "ndgov_svcitdvmvcauto" -Environment "Agent" -Name "ZM-Test\Test-ITDSchedule" -Paused +New-PSUSchedule -Cron "0 * * * *" -Script "Infra-VMware.Snapshot\Remove-ITDVMwareVMSnapshotExpired.ps1" -TimeZone "America/Chicago" -Name "Remove-ITDVMwareVMSnapshotExpired" -RandomDelay +New-PSUSchedule -Cron "0 */1 * * *" -Script "Infra-VMware.VirtualMachine\Sync-ITDServerBuildRITMs.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDServerBuildRITMs.ps1" -RandomDelay -RandomDelayMaximum 600 +New-PSUSchedule -Cron "*/20 * * * *" -Script "Infra-VMware.VirtualMachine\Update-ITDSnowVMTaskDescription.ps1" -TimeZone "America/Chicago" -Name "Update-ITDSnowVMTaskDescription" -RandomDelay +New-PSUSchedule -Cron "13 8-17 * * *" -Script "Infra-Servers-PowerShellUniversal\Update-ITDModule.ps1" -TimeZone "America/Chicago" -Name "Update-ITDModule.ps1" -RandomDelay -RandomDelayMaximum 600 +New-PSUSchedule -Cron "27 8-16/2 * * 1-5" -Script "ITD-WindowsServer.Lifecycle\Remove-ITDWindowsServer.ps1" -TimeZone "America/Chicago" -Name "Remove-ITDWindowsServer" -RandomDelay -RandomDelayMaximum 300 +New-PSUSchedule -Cron "23 * * * *" -Script "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMTagsFromCmdb.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDVMwareVMTagsFromCmdb" +New-PSUSchedule -Cron "7/30 8-16 * * *" -Script "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Auto.ps1" -TimeZone "America/Chicago" -Name "New-ITDWindowsVm_Auto" +New-PSUSchedule -Cron "0 13 * * 1-5" -Script "Infra-VMware.VirtualMachine\Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -TimeZone "America/Chicago" -Parameters @{ + All = $true +} -Name "Move-ITDVMwareVMToAppNameFolder_Auto" +New-PSUSchedule -Cron "33 8-16/2 * * *" -Script "Infra-VMware.VirtualMachine\Set-ITDVMwareVMTagFromCmdb.ps1" -TimeZone "America/Chicago" -Parameters @{ + NewBuilds = $true +} -Name "Set-ITDVMwareVMTagFromCmdb_NewBuilds" +New-PSUSchedule -Cron "4 8 * * MON-FRI" -Script "Infra-VMware.VirtualMachine\Set-ITDVMwareVMTagFromCmdb.ps1" -TimeZone "America/Chicago" -Parameters @{ + All = $true +} -Name "Set-ITDVMwareVMTagFromCmdb_All" +New-PSUSchedule -Cron "0 0 * * *" -Script "ZM-Test\Test-ITDScheduleWithCreds.ps1" -TimeZone "America/Chicago" -Name "Test-ITDScheduleWithCreds.ps1" +New-PSUSchedule -Cron "15 10 * * MON-FRI" -Script "Infra-VMware.Administration\Update-ITDVMwareILOSslCertificate.ps1" -TimeZone "America/Chicago" -Parameters @{ + SynergyDiscovery = $true +} -Name "Update-ITDVMwareILOSslCertificate.ps1" +New-PSUSchedule -Cron "0 11 * * *" -Script "Infra-Certificate-External.Sectigo\Invoke-CertAutoRenew.ps1" -TimeZone "America/Chicago" -Name "Invoke-CertAutoReview.ps1" +New-PSUSchedule -Cron "0 8 * * *" -Script "Infra-VMware.Administration\Sync-ITDVMwareVMMetadataToSql.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDVMwareVMMetadataToSql.ps1" +New-PSUSchedule -Cron "0 8 * * *" -Script "Infra-VMware.Administration\Sync-ITDVMwareHostMetadataToSql.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDVMwareHostMetadataToSql.ps1" +New-PSUSchedule -Cron "0 8 * * *" -Script "Infra-VMware.Administration\Sync-ITDVMwareClusterMetadataToSql.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDVMwareClusterMetadataToSql.ps1" +New-PSUSchedule -Cron "0 8 * * *" -Script "Infra-VMware.Administration\Sync-ITDOneViewServerInventoryToSql.ps1" -Name "Sync-ITDOneViewServerInventoryToSql.ps1" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/scripts.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/scripts.ps1 new file mode 100644 index 0000000..6a2ea18 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/scripts.ps1 @@ -0,0 +1,56 @@ +New-PSUScript -Name "New-ITDPSUScript.ps1" -Description "New-ITDPSUScript.ps1" -Tag @('Infra-VMware_Execute','Team-Windows_Execute') -Path "Infra-Servers-PowerShellUniversal\New-ITDPSUScript.ps1" -Environment "Integrated" +New-PSUScript -Name "New-ITDVMwareVMSnapshotTask.ps1" -Description "New-ITDVMwareVMSnapshotTask.ps1" -Tag @('Team-Windows_Execute','Team-Network_Execute','Infra-VMware_Modify','Team-Linux_Execute','Team-CND_Execute','Team-Tier2_Execute','Team-Collaboration_Execute') -Path "Infra-VMware.Snapshot\New-ITDVMwareVMSnapshotTask.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" +New-PSUScript -Name "Update-ITDVMwareVMSnapshotStatus.ps1" -Description "Update-ITDVMwareVMSnapshotStatus.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Snapshot\Update-ITDVMwareVMSnapshotStatus.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" +New-PSUScript -Name "Remove-ITDVMwareVMSnapshotExpired.ps1" -Description "Remove-ITDVMwareVMSnapshotExpired.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Snapshot\Remove-ITDVMwareVMSnapshotExpired.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" +New-PSUScript -Name "Test-ITDSchedule.ps1" -Description "Test-ITDSchedule.ps1" -Tag @('Infra-VMware_Modify') -Path "ZM-Test\Test-ITDSchedule.ps1" +New-PSUScript -Name "New-ITDADServiceAccount.ps1" -Description "New-ITDADServiceAccount.ps1" -Tag @('Team-Windows_Execute','ITD-WindowsServer_Modify') -Path "Infra-ActiveDirectory.Object\New-ITDADServiceAccount.ps1" -Environment "Agent" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuad" +New-PSUScript -Name "Approve-ITDWindowsServer.ps1" -Description "Approve-ITDWindowsServer.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\Approve-ITDWindowsServer.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Remove-ITDWindowsServer.ps1" -Description "Remove-ITDWindowsServer.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\Remove-ITDWindowsServer.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Update-ITDModule.ps1" -Description "Update-ITDModule.ps1" -Tag @('Infra-VMware_Execute','Team-Windows_Execute','Infra-VMware_Modify') -Path "Infra-Servers-PowerShellUniversal\Update-ITDModule.ps1" -Environment "7.4.13" +New-PSUScript -Name "Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Description "Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Tag @('Infra-VMware_Modify','Team-Mgmt_Execute') -Path "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaassprw" +New-PSUScript -Name "Sync-ITDServerBuildRITMs.ps1" -Description "Sync-ITDServerBuildRITMs.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Sync-ITDServerBuildRITMs.ps1" -Environment "Agent" +New-PSUScript -Name "Update-ITDSnowVMTaskDescription.ps1" -Description "Update-ITDSnowVMTaskDescription.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Update-ITDSnowVMTaskDescription.ps1" -Environment "Agent" -ErrorAction "Stop" +New-PSUScript -Name "Add-ITDADUserSPN.ps1" -Description "Add-ITDADUserSPN.ps1" -Tag @('Team-Windows_Execute','ITD-WindowsServer_Modify') -Path "Infra-ActiveDirectory.Object\Add-ITDADUserSPN.ps1" -Environment "Agent" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuad" +New-PSUScript -Name "New-ITDWindowsVmVMware_Manual.ps1" -Description "New-ITDWindowsVmVMware_Manual.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\New-ITDWindowsVmVMware_Manual.ps1" -Environment "Agent" -DisableManualInvocation -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Manual.ps1" -Description "New-ITDWindowsVmAzure_Manual.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\New-ITDWindowsVmAzure_Manual.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Get-ITDVMwareVMGuestIPsForPA.ps1" -Description "Get-ITDVMwareVMGuestIPsForPA.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Get-ITDVMwareVMGuestIPsForPA.ps1" +New-PSUScript -Name "Test-PSUVariable.ps1" -Description "Test-PSUVariable.ps1" -Tag @('Infra-VMware_Execute') -Path "ZM-Test\Test-PSUVariable.ps1" +New-PSUScript -Name "Get-ITDVMwareLunIdNextAvailable.ps1" -Description "Get-ITDVMwareLunIdNextAvailable.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Get-ITDVMwareLunIdNextAvailable.ps1" +New-PSUScript -Name "Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Description "Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Add-ITDSolarwindsNode.ps1" -Description "Add-ITDSolarwindsNode.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Add-ITDSolarwindsNode.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Remove-ITDSolarwindsNode.ps1" -Description "Remove-ITDSolarwindsNode.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Remove-ITDSolarwindsNode.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Get-ITDExpiredFiles.ps1" -Description "Get-ITDExpiredFiles.ps1" -Tag @('Team-Windows_Execute','ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.FileManagement\Get-ITDExpiredFiles.ps1" -Environment "PowerShell 7" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuwin" +New-PSUScript -Name "test-sql.ps1" -Description "test-sql.ps1" -Path "ZM-Test\test-sql.ps1" +New-PSUScript -Name "New-ITDWindowsVmVMware_Step1.ps1" -Description "New-ITDWindowsVmVMware_Step1.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmVMware_Step1.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmVMware_Step2.ps1" -Description "New-ITDWindowsVmVMware_Step2.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmVMware_Step2.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Add-ITDServerBuildRitmToSql.ps1" -Description "Add-ITDServerBuildRitmToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Add-ITDServerBuildRitmToSql.ps1" -Environment "Agent" +New-PSUScript -Name "Sync-ITDVMwareVMTagsFromCmdb.ps1" -Description "Sync-ITDVMwareVMTagsFromCmdb.ps1" -TimeOut "600" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMTagsFromCmdb.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "New-ITDWindowsVm_Step3.ps1" -Description "New-ITDWindowsVm_Step3.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Step3.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Step1.ps1" -Description "New-ITDWindowsVmAzure_Step1.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmAzure_Step1.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Step2.ps1" -Description "New-ITDWindowsVmAzure_Step2.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmAzure_Step2.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVm_Auto.ps1" -Description "New-ITDWindowsVm_Auto.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Auto.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Get-HelloWorld.ps1" -Description "Get-HelloWorld.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ZM-Test\Get-HelloWorld.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Test-InvokeZM.ps1" -Description "Test-InvokeZM.ps1" -Path "ZM-Test\Test-InvokeZM.ps1" +New-PSUScript -Name "New-TestNestedInvoke.ps1" -Description "New-TestNestedInvoke.ps1" -Tag @('Team-Windows_Modify') -Path "ZM-Test\New-TestNestedInvoke.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Set-ITDVMwareVMTagFromCmdb.ps1" -Description "Set-ITDVMwareVMTagFromCmdb.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Set-ITDVMwareVMTagFromCmdb.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Description "Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "Test-AzIaaSCredential.ps1" -Description "Test-AzIaaSCredential.ps1" -Path "ZM-Test\Test-AzIaaSCredential.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Remove-ITDExpiredFiles_Auto.ps1" -Description "Remove-ITDExpiredFiles_Auto.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.FileManagement\Remove-ITDExpiredFiles_Auto.ps1" -Environment "PowerShell 7" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuwin" +New-PSUScript -Name "Test-ZMFile.ps1" -Description "Test-ZMFile.ps1" -Tag @('Infra-VMware_Execute','Team-Windows_Execute') -Path "ZM-Test\Test-ZMFile.ps1" +New-PSUScript -Name "Update-ITDVMwareILOSslCertificate.ps1" -Description "Update-ITDVMwareILOSslCertificate.ps1" -TimeOut "300" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Update-ITDVMwareILOSslCertificate.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Test-ZMVariable.ps1" -Description "Test-ZMVariable.ps1 [[-variable1] ] [[-variable2] ]" -Path "ZM-Test\Test-ZMVariable.ps1" +New-PSUScript -Name "Test-ITDScheduleWithCreds.ps1" -Description "Test-ITDScheduleWithCreds.ps1" -Path "ZM-Test\Test-ITDScheduleWithCreds.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDCertificateRequestSectigo.ps1" -Description "New-ITDCertificateRequestSectigo.ps1" -Tag @('Team-Windows_Execute','Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\New-ITDCertificateRequestSectigo.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Unregister-CommonName.ps1" -Description "Unregister-CommonName.ps1" -Tag @('Team-Windows_Execute','Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Unregister-CommonName.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Invoke-CertAutoRenew.ps1" -Description "Invoke-CertAutoRenew.ps1" -Tag @('Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Invoke-CertAutoRenew.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "New-SectigoPfxCertificate.ps1" -Description "New-SectigoPfxCertificate.ps1" -Tag @('Team-Windows_Execute','Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\New-SectigoPfxCertificate.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Deploy-Client.ps1" -Description "Deploy-Client.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-ActiveDirectory.Object\Deploy-Client.ps1" +New-PSUScript -Name "Troubleshooting.ps1" -Description "Troubleshooting.ps1" -Tag @('Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Troubleshooting.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Register-CommonName.ps1" -Description "Register-CommonName.ps1" -TimeOut "60" -Tag @('Team-Windows_Execute','Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Register-CommonName.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Update-Client.ps1" -Description "Update-Client.ps1" -Tag @('Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Update-Client.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdpsuwin" +New-PSUScript -Name "Get-RegistrationList .ps1" -Description "Get-RegistrationList .ps1" -Tag @('Team-Windows_Execute','Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Get-RegistrationList .ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Invoke-CertificateDeploy.ps1" -Description "Invoke-CertificateDeploy.ps1" -Tag @('Infra-Certificate_Modify') -Path "Infra-Certificate-External.Sectigo\Invoke-CertificateDeploy.ps1" -Environment "PowerShell 7" +New-PSUScript -Name "Sync-ITDVMwareClusterMetadataToSql.ps1" -Description "Sync-ITDVMwareClusterMetadataToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Sync-ITDVMwareClusterMetadataToSql.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmvcro" +New-PSUScript -Name "Sync-ITDVMwareHostMetadataToSql.ps1" -Description "Daily VMware Host metadata report for PowerBI trending and hardware capacity planning." -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Sync-ITDVMwareHostMetadataToSql.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmvcro" +New-PSUScript -Name "Sync-ITDVMwareVMMetadataToSql.ps1" -Description "Sync-ITDVMwareVMMetadataToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Sync-ITDVMwareVMMetadataToSql.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmvcro" +New-PSUScript -Name "Sync-ITDOneViewServerInventoryToSql.ps1" -Description "Sync-ITDOneViewServerInventoryToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Sync-ITDOneViewServerInventoryToSql.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmhpe" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/settings.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/settings.ps1 new file mode 100644 index 0000000..8c4c2a2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/settings.ps1 @@ -0,0 +1,6 @@ +$Parameters = @{ + LogLevel = "Error" + HideRunAs = $true + HideRunOn = $true +} +Set-PSUSetting @Parameters \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/tags.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/tags.ps1 new file mode 100644 index 0000000..c1ee2c2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/tags.ps1 @@ -0,0 +1,21 @@ +New-PSUTag -Name "Infra-VMware_Execute" -Color "#d4380d" +New-PSUTag -Name "Team-Windows_Execute" -Color "#391085" +New-PSUTag -Name "Team-Network_Execute" -Color "#c41d7f" +New-PSUTag -Name "Infra-VMware_Modify" -Color "#fa541c" +New-PSUTag -Name "Team-Windows_Modify" -Color "#722ed1" +New-PSUTag -Name "Team-Network_Modify" -Color "#f759ab" +New-PSUTag -Name "Team-Linux_Execute" -Color "#096dd9" +New-PSUTag -Name "Team-Linux_Modify" -Color "#40a9ff" +New-PSUTag -Name "Team-CND_Execute" -Color "#096dd9" +New-PSUTag -Name "Team-CND_Modify" -Color "#40a9ff" +New-PSUTag -Name "Team-Tier2_Execute" -Color "#389e0d" +New-PSUTag -Name "Team-Tier2_Modify" -Color "#7cb305" +New-PSUTag -Name "Shared-PowerSchool_Execute" +New-PSUTag -Name "Shared-PowerSchool_Modify" +New-PSUTag -Name "ITD-WindowsServer_Execute" -Color "#874d00" +New-PSUTag -Name "ITD-WindowsServer_Modify" -Color "#d48806" +New-PSUTag -Name "Team-Mgmt_Execute" -Color "#780650" +New-PSUTag -Name "Team-Mgmt_Modify" -Color "#c41d7f" +New-PSUTag -Name "Team-Collaboration_Execute" -Color "#ffe58f" +New-PSUTag -Name "Team-Collaboration_Modify" -Color "#ffd666" +New-PSUTag -Name "Infra-Certificate_Modify" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/variables.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/variables.ps1 new file mode 100644 index 0000000..c9c8e7e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/.universal/variables.ps1 @@ -0,0 +1,16 @@ +New-PSUVariable -Name "sql_itdpsu1" -Vault "Database" -Type "PSCredential" +New-PSUVariable -Name "ndgov_svcitdvmsnapmgr" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdvmvcauto" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" -Role @('App-Infra-VMware') +New-PSUVariable -Name "ndgov_svcitdpsuad" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('Team-Windows','Team-Tier2','App-Infra-VMware') +New-PSUVariable -Name "snow_vmcred" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdiaasauto" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer','Administrator') +New-PSUVariable -Name "ndgov_itdsccmsrvcpia" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer') +New-PSUVariable -Name "ndgov_svcitdpsuwin" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer','Team-Windows') +New-PSUVariable -Name "ndgov_svcitdvmvcro" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdiaassprw" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_itdvcenterscript" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" -Role @('App-Infra-VMware') +New-PSUVariable -Name "azure_iaasserviceprincipal" -Vault "Database" -Type "System.String" -Description "Owner: App-ITD-WindowsServer" -Role @('App-ITD-WindowsServer','Administrator') +New-PSUVariable -Name "SectigoClientSecret" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-Certificate-External" +New-PSUVariable -Name "ndgov_svcitdvmhpe" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" -Role @('App-Infra-VMware','Administrator') +New-PSUVariable -Name "sectigo_vmware" -Vault "Database" -Type "PSCredential" -Role @('App-Infra-VMware','Administrator') +New-PSUVariable -Name "pwdvault_WindowsCertificates" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-Certificate-External" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 new file mode 100644 index 0000000..9cdc2aa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 @@ -0,0 +1,13 @@ +Param( + [string] + $ComputerName +) + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + $GetITDExpiredFilesParams = @{ + ComputerName = $ComputerName; + } + Get-ITDExpiredFiles @GetITDExpiredFilesParams -Credential $Secret:ndgov_svcitdpsuwin -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName | Format-Table -AutoSize +} Else { + Get-ITDExpiredFiles -Credential $Secret:ndgov_svcitdpsuwin -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName | Format-Table -AutoSize +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles_Auto.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles_Auto.ps1 new file mode 100644 index 0000000..d38edf9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles_Auto.ps1 @@ -0,0 +1,119 @@ + +[CmdletBinding()] +param ( + [string] + $ComputerName, + + [switch] + $WhatIf +) + + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$FilesRemovedSuccess = @() +$FilesRemovedFailure = @() +$GetITDExpiredFilesAutoParams += @{} + +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } +} + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + Write-Verbose -Message "ComputerName parameter found" -Verbose + $GetITDExpiredFilesParams = @{ + Credential = $Secret:ndgov_svcitdpsuwin + } + $GetITDExpiredFilesParams += @{ + ComputerName = $ComputerName; + } +} + +$FilesToRemove = Get-ITDExpiredFiles @GetITDExpiredFilesParams +Write-Verbose -Message ("Found " + $FilesToRemove.count + " expired files to remove") -Verbose + +ForEach ($File in $FilesToRemove) { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName ) + $ComputerName = $File.PSComputerName + $DateTime = Get-Date + $FullName = $File.FullName + + $InvokeCommandParams = @{ + ComputerName = $File.PSComputerName; + #Credential = $Secret:ndgov_svcitdpsuwin; + ErrorAction = 'Stop'; + ArgumentList = @($File.FullName); + ScriptBlock = { Get-Item -Path $args[0] | Remove-Item } + } + + switch ($WhatIf) { + $true { + Write-Verbose -Message "WhatIf switch true" -Verbose + try { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + Write-Host -Message ($Server.ComputerName + " -- " + 'What if: Performing the operation "Remove File" on target ' + $File.FullName) + # log success + $FilesRemovedSuccess += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + }#> + Write-Output $File + } + catch { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure + $FilesRemovedFailure += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + } + } + Default { + try { + Write-Verbose -Message "WhatIf switch default" -Verbose + Invoke-Command @InvokeCommandParams + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + # log success to sql, add obj to array + $SqlQuery = "INSERT INTO [$Table] (PSUJobId, DateTime, ComputerName, Status, FullName) Values ('$PSUJobId', '$DateTime', '$ComputerName', 'Success', '$FullName')" + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + $FilesRemovedSuccess += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + Write-Output $File + } + catch { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure to sql, add obj to array + $SqlQuery = "INSERT INTO [$Table] (PSUJobId, DateTime, ComputerName, Status, FullName) Values ('$PSUJobId', '$DateTime', '$ComputerName', 'Failure', '$FullName')" + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + $FilesRemovedFailure += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + } + } + } + + # create CHG request for the work + Write-Verbose -Message "Submit CHG for the work. TBD" -Verbose + + Write-Verbose -Message ("End~" + $File.PSComputerName + "~" + $File.FullName ) -Verbose + ### Generate CHG +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 new file mode 100644 index 0000000..1bec9fe --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 @@ -0,0 +1,146 @@ +# cron expression +# 47 8-16 * * 1-5 + +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number.value + Write-Verbose -Message "Start $SCTasknum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + $ComputerName = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $OperatingSystem = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).operating_system + + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + $FormFQDN = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $FormHostName = $FormFQDN.split('.')[0] + + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + # Ci does not exist + Write-Verbose -Message ("Ci not found") -Verbose + } + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Other' } + } + + Write-Verbose -Message "Confirm all agents are running" + $ProcessList = @('ccmexec', 'cohesity*', 'nessus*', 'cortex*') + switch ($target_platform) { + 'VMware' { + $ProcessList += 'vmtoolsd' + } + 'Azure' { + Write-Verbose -Message "vmtoolsd not required for Azure VM" + } + Default { + Write-Verbose -Message "no Ci means no platform check" + } + } + } + catch { + Write-Error $error[0] + } + + If ( $ComputerName -like "*.nd.gov" ) { + try { + $AgentCount = 0 + $svcitdpsuwin = Get-ITDPassword -UserName ndgov\svcitdpsuwin -Title ndgov\svcitdpsuwin + $RunningProcess = Invoke-Command -Credential $svcitdpsuwin -ComputerName $FormFQDN -ArgumentList $ProcessList -ErrorAction Stop -ScriptBlock { + Get-Process + } + + If ($RunningProcess) { + ForEach ($ProcessName in $ProcessList) { + If ($RunningProcess -match $ProcessName) { + Write-Verbose -Message "Process $ProcessName found." -Verbose + $AgentCount = $AgentCount + 1 + } + Else { + Write-Warning -Message "Process $ProcessName not found" + # do not increase agentcount count + } + } + } + } + catch [System.Management.Automation.Remoting.PSRemotingTransportException] { + Write-Warning -Message "$FormFQDN unreachable via PSRemoting" + $BuildComplete = $false + } + } Else { + Write-Verbose -Message ($SCTaskNum + $ComputerName + " is not nd.gov, manual agent validation required.") -Verbose + } + + <# if Task has been open for more than x hours, update description for humans to review + $Hours = 6 + If ($SCTask.opened_at.value -lt (Get-Date).AddHours(-$Hours)) { + $work_notes = ("New build Ci has not been found after $Hours hours, problem may have occurred. Please review.`nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $OperatingSystem VM Build for $ComputerName, NEED HUMAN REVIEW" + + <#Update-ServiceNowRecord -ID $SCTask.number -Values @{ + work_notes = $work_notes; + shortdescription = $shortdescription; + } + }#> + + If ($AgentCount -ge @($ProcessList).count) { + Write-Verbose "All required processes running, Windows is ready for use. Update SCTask to notify physical/virtual hardware stakeholders." -Verbose + $work_notes = ("$target_platform $hardware_type $FormFQDN Windows Guest OS complete. `nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $hardware_type $FormFQDN Windows Guest OS complete." + + Write-Verbose -Message "Work notes: $work_notes" -Verbose + Write-Verbose -Message "Short description: $shortdescription" -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $work_notes; + close_notes = "$FQDN $target_platform Windows Guest OS complete."; + short_description = $shortdescription; + state = 'Closed Complete' + } + } + + Write-Verbose -Message "End $SCTasknum" -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 new file mode 100644 index 0000000..da5a051 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 @@ -0,0 +1,130 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + ComputerName = $ComputerName; + AppName = $AppName; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("ComputerName " + $NewITDWindowsVMAzureParams.ComputerName) -Verbose +Write-Verbose -Message ("CPU " + $NewITDWindowsVMAzureParams.CPU) -Verbose +Write-Verbose -Message ("MemoryGB " + $NewITDWindowsVMAzureParams.MemoryGB) -Verbose +Write-Verbose -Message ("DiskOsGB" + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS" + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("Environment" + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName" + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions" + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose + +New-ITDWindowsVmAzure @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 new file mode 100644 index 0000000..d81c74c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 @@ -0,0 +1,118 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 50, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskSwapGB = ($MemoryGB + 1), + + [Parameter(ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet = '10.11.12.0/23', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment = 'Test', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Datacenter = 'Mandan', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName = 'ITD-POC-zmeier', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $StartupPriority = 5, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = "No Licensing Restrictions" +) + +switch ($PSCMdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareParams = @{ + ComputerName = $ComputerName; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskSwapGB = $DiskSwapGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + Datacenter = $Datacenter; + AppName = $AppName; + StartupPriority = $StartupPriority; + LicensingRestrictions = $LicensingRestrictions; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmVMwareParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskSwapGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_2_swap_disk ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + Datacenter = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).data_center ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + StartupPriority = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).startup_priority ); + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + } +} + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt server provisioning" -Verbose +Write-Host $NewITDWindowsVmVMwareParams +New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose +Write-Warning -Message "New-ITDWindowsVmVMware function completed" + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 new file mode 100644 index 0000000..f26f565 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 @@ -0,0 +1,176 @@ +[CmdletBinding()] # +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(ParameterSetName = 'FromSCTask')] + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry', HelpMessage = "Example: Standard_D4ds_v5")] + [string] + $VMSizeOverride, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + FQDN = $FQDN; + AppName = $AppName; + VMSizeOverride = $VMSizeOverride; + #CPU = $CPU; + #MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + VMEnvironment = $VMEnvironment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { + Write-Warning -Message "ResourceGroupNameOverride found $AvailabilityZone" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + 'VMSizeOverride' { + Write-Warning -Message "VMSizeOverride found $VMSizeOverride" + $NewITDWindowsVMAzureParams += @{ VMSizeOverride = $VMSizeOverride } + } + } + If ($NewITDWindowsVmAzureParams.VMSizeOverride) { + # do nothing + } Else { + $NewITDWindowsVMAzureParams += @{ CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors );} + $NewITDWindowsVMAzureParams += @{ MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb );} + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "Attempt server provisioning" -Verbose +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("FQDN " + $NewITDWindowsVMAzureParams.FQDN) -Verbose +Write-Verbose -Message ("VMSizeOverride " + $NewITDWindowsVMAzureParams.VMSizeOverride) -Verbose +Write-Verbose -Message ("DiskOsGB " + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS " + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("VMEnvironment " + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName " + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions " + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose +try { + New-ITDWindowsVmAzureStep1 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Verbose -Message "New-ITDWindowsVmAzureStep1 function completed" + $Step1Complete = $true +} +catch { + $Step1Complete = $false + switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + $ErrorText = ($_.ErrorDetails.message | ConvertFrom-Json).text + If ($ErrorText -match "Cannot find 1 available IP address" ) { + $Msg = "Resolve the issue and resubmit the Server Build Request catalog item. Setting $SCTaskNum State to Closed Incomplete" + Write-Warning -Message $Msg + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("Azure build step 1 errored. $Msg. `nPSU Job Id #" + $UAJob.Id + " `n" + $ErrorText) + state = 'Closed Incomplete' + } + } + } + } + throw +} + + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + Write-Verbose -Message ("Update " + $SCTaskNum + " with Step 1 status") -Verbose + switch ($Step1Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("Azure build step 1 complete. `nPSU Job Id #" + $UAJob.Id) + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("Azure build step 1 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig new file mode 100644 index 0000000..ebe8f98 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig @@ -0,0 +1,151 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] +<<<<<<< HEAD + [string] + $VMSizeOverride, +<<<<<<< HEAD +<# +======= + <# +>>>>>>> main + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] +======= +>>>>>>> 828a9d5a994531efc47fe9ca78c93cfb076c6ba4 + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + ComputerName = $ComputerName; + AppName = $AppName; +<<<<<<< HEAD +<<<<<<< HEAD + VMSizeOverride = $VMSizeOverride; +======= + VMSizeOverride = $VMSizeOverride; +>>>>>>> main + #CPU = $CPU; + #MemoryGB = $MemoryGB; +======= + CPU = $CPU; + MemoryGB = $MemoryGB; +>>>>>>> 828a9d5a994531efc47fe9ca78c93cfb076c6ba4 + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("ComputerName " + $NewITDWindowsVMAzureParams.ComputerName) -Verbose +Write-Verbose -Message ("CPU " + $NewITDWindowsVMAzureParams.CPU) -Verbose +Write-Verbose -Message ("MemoryGB " + $NewITDWindowsVMAzureParams.MemoryGB) -Verbose +Write-Verbose -Message ("DiskOsGB" + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS" + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("Environment" + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName" + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions" + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose + +New-ITDWindowsVmAzureStep1 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 new file mode 100644 index 0000000..432e53e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 @@ -0,0 +1,75 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + FQDN = $FQDN; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + AppName = ( (Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).application_info).Name.display_value); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("FQDN " + $NewITDWindowsVMAzureParams.FQDN) -Verbose + +try { + New-ITDWindowsVmAzureStep2 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Warning -Message "New-ITDWindowsVmAzureStep2 function completed" + $Step2Complete = $true +} +catch { + Write-Error -Message $error[0] + $Step2Complete = $false + throw +} + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + switch ($Step2Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("Azure build step 2 complete. `nPSU Job Id #" + $UAJob.Id); + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("Azure build step 2 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 new file mode 100644 index 0000000..8332bb2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 @@ -0,0 +1,157 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 50, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskSwapGB = ($MemoryGB + 1), + + [Parameter(ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet = '10.11.12.0/23', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment = 'Test', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Datacenter = 'Mandan', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName = 'ITD-POC-zmeier', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $StartupPriority = 5, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = "No Licensing Restrictions" +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareParams = @{ + FQDN = $FQDN; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskSwapGB = $DiskSwapGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + VMEnvironment = $VMEnvironment; + Datacenter = $Datacenter; + AppName = $AppName; + StartupPriority = $StartupPriority; + LicensingRestrictions = $LicensingRestrictions; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmVMwareParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskSwapGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_2_swap_disk ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + Datacenter = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).data_center ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + StartupPriority = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).startup_priority ); + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + } +} + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt server provisioning" -Verbose +Write-Verbose -Message $NewITDWindowsVmVMwareParams +try { + New-ITDWindowsVmVMwareStep1 @NewITDWindowsVmVMwareParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Verbose -Message "New-ITDWindowsVmVMwareStep1 function completed" + $Step1Complete = $true +} +catch { + $Step1Complete = $false + switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + $ErrorText = ($_.ErrorDetails.message | ConvertFrom-Json).text + If ($ErrorText -match "Cannot find 1 available IP address" ) { + $Msg = "Resolve the issue and resubmit the Server Build Request catalog item. Setting $SCTaskNum State to Closed Incomplete" + Write-Warning -Message $Msg + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 1 errored. $Msg. `nPSU Job Id #" + $UAJob.Id + " `n" + $ErrorText) + state = 'Closed Incomplete' + } + } + } + } + throw +} + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + Write-Verbose -Message ("Update " + $SCTaskNum + " with Step 1 status") -Verbose + switch ($Step1Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 1 complete. `nPSU Job Id #" + $UAJob.Id) + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 1 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 new file mode 100644 index 0000000..78cf35a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 @@ -0,0 +1,87 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment +) + +switch ($PSCMdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareStep2Params = @{ + FQDN = $FQDN; + AppName = $AppName; + VMEnvironment = $VMEnvironment; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + Write-Verbose -Message ("Ritm: " + $Ritm.Number) -Verbose + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + Write-Verbose -Message ("FqdnFromSCTaskDescription: " + ($SCTask.short_description).display_value.split(' ')[7] ) -Verbose + $NewITDWindowsVmVMwareStep2Params = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + VMEnvironment = ( ($Ritm.CustomVariable).environment.value ); + AppName = ( (Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).application_info).Name.display_value); + } + + Write-Verbose -Message ("Params FQDN: " + $NewITDWindowsVmVMwareStep2Params.FQDN) -Verbose + } +} + + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt VMware step 2" -Verbose +Write-Host $NewITDWindowsVmVMwareStep2Params +try { + New-ITDWindowsVmVMwareStep2 @NewITDWindowsVmVMwareStep2Params -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Warning -Message "New-ITDWindowsVmVMwareStep2 function completed" + $Step2Complete = $true +} +catch { + Write-Error -Message $error[0] + $Step2Complete = $false + throw +} + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + switch ($Step2Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VM build step 2 complete. `nPSU Job Id #" + $UAJob.Id); + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 2 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 new file mode 100644 index 0000000..5bfc1d7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 @@ -0,0 +1,146 @@ +<# +.SYNOPSIS + Processes automated server build tasks for Windows machines in ServiceNow, triggered via PowerShell Universal. +.DESCRIPTION + This script connects to the ServiceNow API, retrieves open catalog tasks that match a specific filter for automated server build tasks, + and processes them. This script is designed to run as a scheduled task. It can optionally filter tasks by a specific SCTask number. +.PARAMETER SCTaskNum + The ServiceNow task number to filter the tasks. If not provided, all tasks matching the filter will be processed. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 + This example runs the script and processes all open tasks that match the filter for automated server build tasks. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 -SCTaskNum 'SCTASK0012345' + This example runs the script and processes only the task with the specified SCTask number. +.NOTES + Ensure that the ServiceNow instance URL and credentials are correctly configured in the New-ITDServiceNowSession function. + This script is not supported in Linux. +#> + +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter -IncludeTotalCount | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + <# + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } +#> + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + { $_ -match "human review" } { + Write-Verbose -Message "Human review required, skipping" -Verbose + Break + } + { $_ -match "build step 2 complete" } { + # execute Step 3 + Write-Verbose -Message "Step 2 already complete, starting step 3" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVm_Step3.ps1" -SCTaskNum $SCTaskNum + #$WorkNotesMsg = ("VMware build Step 3 started.`nPSU Job Id #" + $PSUJob.Id) + Break + } + { $_ -match "build Step 2 started"} { + Write-Verbose -Message "Step 2 already started, skipping" -Verbose + Break + } + { $_ -match "build step 1 complete" } { + # execute Step 2 + Write-Verbose -Message "Step 1 already complete, starting Step 2" -Verbose + # Determine if VMware or Azure and run appropriate build Step 2 function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step2.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmVMware_Step2.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + { $_ -match "build Step 1 started"} { + Write-Verbose -Message "Step 1 already started, skipping" -Verbose + Break + } + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmVMware_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + If($null -eq $WorkNotesMsg){ + # do nothing + } Else { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{work_notes = $WorkNotesMsg } + } + + Write-Verbose -Message "End $SCTaskNum" -Verbose +} + +#> + +#Invoke-PSUScript -Name New-ITDWindowsVmVMware_Step1.ps1 -SCTaskNum "SCTASK0310457" + + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 new file mode 100644 index 0000000..c53bec4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 @@ -0,0 +1,126 @@ +# used by both Azure and VMware build tasks + +[CmdletBinding()] +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTASK')] + [string] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN +) + +# get FQDN from SCTask/Ritm, or directly from user input +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + Write-Verbose -Message "FQDN manually entered" + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + Write-Verbose -Message ("Ritm: " + $Ritm.Number) -Verbose + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + Write-Verbose -Message ("FqdnFromSCTaskDescription: " + ($SCTask.short_description).display_value.split(' ')[7] ) -Verbose + + $FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ).tolower(); + $OperatingSystem = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).operating_system + } +} + +try { + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } +<# Is this needed? + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + # Ci does not exist + Write-Verbose -Message ("Ci not found") -Verbose + } + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Other' } + } +#> + Write-Verbose -Message "Confirm all required agents are running" + $ProcessList = @('ccmexec', 'cohesity*', 'nessus*', 'cortex*') + switch ($target_platform) { + 'VMware' { + $ProcessList += 'vmtoolsd' + } + 'Azure' { + Write-Verbose -Message "No Azure specific agents to check for" -Verbose + } + Default { + Write-Verbose -Message "no Ci means no platform check" + } + } +} +catch { + Write-Error $error[0] +} + +If ( $FQDN -like "*.nd.gov" ) { + try { + $AgentCount = 0 + $svcitdpsuwin = Get-ITDPassword -UserName ndgov\svcitdpsuwin -Title ndgov\svcitdpsuwin + $RunningProcess = Invoke-Command -Credential $svcitdpsuwin -ComputerName $FQDN -ErrorAction Stop -ScriptBlock { + Get-Process + } + + If ($RunningProcess) { + ForEach ($ProcessName in $ProcessList) { + If ($RunningProcess -match $ProcessName) { + Write-Verbose -Message "Process $ProcessName found." -Verbose + $AgentCount = $AgentCount + 1 + } + Else { + Write-Warning -Message "Process $ProcessName not found" + # do not increase agentcount count + } + } + } + } + catch [System.Management.Automation.Remoting.PSRemotingTransportException] { + Write-Warning -Message "$FQDN unreachable via PSRemoting" + $BuildComplete = $false + } +} +Else { + Write-Verbose -Message ($SCTaskNum + $ComputerName + " is not nd.gov, manual agent validation required.") -Verbose +} + +If ($AgentCount -ge @($ProcessList).count) { + Write-Verbose "All required processes running, Windows is ready for use. Update SCTask to notify physical/virtual hardware stakeholders." -Verbose + $work_notes = ("$target_platform $hardware_type $FQDN Windows Guest OS complete. `nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $hardware_type $FQDN Windows Guest OS complete." + + Write-Verbose -Message "Work notes: $work_notes" -Verbose + Write-Verbose -Message "Short description: $shortdescription" -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $work_notes; + close_notes = "$FQDN $target_platform Windows Guest OS complete."; + short_description = $shortdescription; + state = 'Closed Complete' + } +} + +Write-Verbose -Message "End $SCTasknum" -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/Remove-ITDWindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/Remove-ITDWindowsServer.ps1 new file mode 100644 index 0000000..54e081c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ITD-WindowsServer.Lifecycle/Remove-ITDWindowsServer.ps1 @@ -0,0 +1,92 @@ +param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = "active=true^short_descriptionLIKEWindows Removal for " +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter -IncludeTotalCount | Sort-Object { $_.Number.value } + +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} +$AllRitms = [System.Collections.ArrayList]@() +Write-Verbose -Message ("Number of OpenTasks is " + @($OpenTasks).count) -Verbose + +# retrieve ndgov\svcitdiaasauto password to be used for Remove-ITDWindowsServer function +$svcitdiaasauto = Get-ITDPassword -Title "IaaS Automation Account" -UserName "ndgov\svcitdiaasauto" + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter + +ForEach ($OpenTask in $OpenTasks) { + # get SCTask, Ritm + $SCTask = $OpenTask + $SCTaskNum = $OpenTask.number.display_value + Write-Verbose -Message ("Start " + $SCTaskNum) -Verbose + + If ($SCTask.work_notes.display_value -like "*needs human review*") { + Write-Verbose -Message ($SCTaskNum + " flagged for human review, skipping...") -Verbose + } + Else { + $short_description = $SCTask.short_description.display_value + $short_description_hostname = $short_description.split(' ')[4] + + $RitmNum = $SCTask.request_item.display_value + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $short_description_hostname) + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Ritm.VariableSet | Where-Object .host_name_ref) -ErrorAction Stop + + Write-Verbose -Message "Gathering VariableSet data from $RitmNum" + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($short_description_hostname -eq $TempCi.FQDN.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + If ($MatchFound -eq $false) { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = 'error during Windows decommission, needs human review' + } + Write-Warning -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -WarningAction Continue + } + + $HostName = $Ci.Name.display_value + $FQDN = $Ci.FQDN.display_value + + Write-Verbose -Message ("Ci Name " + $Ci.Name.display_value) -Verbose + Write-Verbose -Message ("Ci FQDN " + $Ci.FQDN.display_value) -Verbose + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Unknown'; $hardware_type = 'Other' } + } + + try { + Write-Verbose -Message "Start Removal of $FQDN, $hardware_platform $hardware_type" -Verbose + Remove-ITDWindowsServer -ComputerName $FQDN -SCTaskNum $SCTaskNum -Credential $svcitdiaasauto -Verbose + Write-Verbose -Message "End Removal of $FQDN" -Verbose + } + catch { + Write-Error $error[0] + } + Write-Verbose -Message "End $SCTasknum" -Verbose + } +} + +Write-Verbose -Message "Disconnect to vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 new file mode 100644 index 0000000..254219d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 @@ -0,0 +1,96 @@ +<# +.SYNOPSIS + Add Service Principal Name to a ITD AD Service Account +.DESCRIPTION + Add Service Principal Name to a ITD AD Service Account +.NOTES + example using setspn: + setspn.exe -s MSSQLSvc/test.nd.gov:1433 ndgov\svctest + setspn.exe -s MSSQLSvc/test:1433 ndgov\svctest + setspn.exe -s MSSQLSvc/test.nd.gov ndgov\svctest + setspn.exe -s MSSQLSvc/test ndgov\svctest + + setspn.exe -s MSSQLSvc/test.nd.gov ndgov\svctest +.LINK + +#> + +[CmdletBinding()] +Param( + [string] + $SamAccountName, + + [Parameter(HelpMessage = "Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $ServicePrincipalName = $null +) + +Write-Verbose -Message "Prep Variables and Connections" +switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { + $ServiceNowEnvironment = 'Test' + } + "ITDWINAUTOP1" { + $ServiceNowEnvironment = 'Production' + } +} +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id +$StartDateTime = Get-Date + +Write-Verbose -Message "Find AD User" -Verbose +$ADUser = Get-ADUser -Identity $SamAccountName -ErrorAction Stop + +Write-Verbose -Message "Add SPN(s)" -Verbose +try { + $ServicePrincipalName | ForEach-Object { + Write-Verbose -Message ("Attempt to add SPN value " + $_) -Verbose + $ADUser | Set-ADUser -ServicePrincipalNames @{Add=$_} + } +} +catch { + Write-Error $Error[0] +} + +Start-Sleep -Seconds 2 + +Write-Verbose -Message "No errors when adding the SPNs, listing the SPNs here for human validation" -Verbose +$ValidateUser = Get-ADUser -Identity $SamAccountName -Properties ServicePrincipalNames | Select-Object SamAccountName, ServicePrincipalNames +$ValidateUser.ServicePrincipalNames + +Write-Verbose -Message "Generate ServiceNow CHG" -Verbose +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + +New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred -Verbose +$NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "ServicePrincipalName added to ndgov\$SamAccountName - PSU Job Id $PSUJobId"; + Description = "ServicePrincipalName added to ndgov\$SamAccountName - PSU Job Id $PSUJobId, see notes for details"; + Justification = "ServicePrincipalName is required to be added to Active Directory Service Accounts by some applications"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Remove the new service principal name from the serviceprincipalname attribute." + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; +} + +$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose +$CHGNum = $CHG.Number.value + +Write-Verbose -Message ("Completing SNow " + $CHG.Number.value) -Verbose +$CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = "ServicePrincipalNames added to ndgov\$SamAccountName - PSU Job Id $PSUJobId`n" + ($ServicePrincipalName | ForEach-Object {$_}) +} +Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Deploy-Client.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Deploy-Client.ps1 new file mode 100644 index 0000000..e035ea3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/Deploy-Client.ps1 @@ -0,0 +1 @@ +# It all starts with a single line of powershell code. \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 new file mode 100644 index 0000000..8f7fa42 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 @@ -0,0 +1,134 @@ +<# +.SYNOPSIS + Creates an Active Directory user/service account for the nd.gov domain +.DESCRIPTION + Creates an Active Directory user/service account for the nd.gov domain. +.NOTES + The PasswordstateList parameter must be validated. If a Passwordstate Password List to the options, ensure that the ndgov\svcitdiaasauto Active Directory has modify access on the Password List. + + Requires Integrated or Agent environment. If not chosen, an erroneous error is caused during the invocation of New-ITDADServiceAccount when the PSCredential object is created to be returned to the user, see below. + [error] Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value." + The agent environment is selected to reduce parameter during script execution, and Run As Credential is enforced as svcitdpsuwin +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0016867 +#> + +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, + HelpMessage = "Only nd.gov domain is supported at this time.")] + [ValidateSet("nd.gov")] + [string] + $DomainName = 'nd.gov', + + [Parameter(Mandatory = $true, + HelpMessage = "This is the account name. This value will also be set on the Active Directory Surname attribute (GivenName or Surname are required for ServiceNow lookups)")] + [string] + $SamAccountName, + + [Parameter(Mandatory = $true, + HelpMessage = "Will be set on the respective Passwordstate record property and Active Directory attribute. '1120' will automatically be appended to the entry.")] + [string] + $Description, + + [Parameter(Mandatory = $true, + HelpMessage = "What goes into the Passwordstate record Title field. Generally a FQDN for the server that will use this service account.")] + [string] + $PasswordstateTitle, + + [Parameter(Mandatory = $true, + HelpMessage = "The Passwordstate Password List where the credentials to be saved. Go here to retrieve the password for the new account.")] + [ValidateSet('CSRC', 'VMware_Systems','Peoplesoft Share PW')] + [string] + $PasswordstateList +) + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$StartDateTime = (Get-Date) +$EndDateTime = $StartDateTime.AddMinutes(1) + +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_ActiveDirectory_Object_NewITDADServiceAccount_NPD" + $ServiceNowEnvironment = 'Test' + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_ActiveDirectory_Object_NewITDADServiceAccount_PRD" + $ServiceNowEnvironment = 'Production' + } +} + +Write-Verbose -Message "fix samaccountname" -Verbose +$SamAccountName = $SamAccountName.Tolower() + +# add to SQL +Write-Verbose -Message "Add request to SQL" -Verbose +$SqlQuery = "INSERT INTO [$SnapshotTable] (PSUJobId,RequestedBy,DateTime,Status,DomainName,SamAccountName,Description,PasswordstateTitle,PasswordstateList) Values ('$PSUJobId', '$RequestedBy', '$StartDateTime','Requested','$DomainName','$SamAccountName', '$Description', '$PasswordstateTitle', '$PasswordstateList');" +Write-Verbose -Message $SqlQuery -Verbose +Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +# Do the work +Write-Verbose -Message "Create the account in Active Directory, and Passwordstate record" -Verbose +New-ITDADServiceAccount -SamAccountName $SamAccountName -Description $Description -PasswordstateList $PasswordstateList -PasswordstateTitle $PasswordstateTitle -Credential $Secret:ndgov_svcitdpsuad -Verbose +Write-Verbose -Message "Executing Get-ADUser -Identity $SamAccountName" -Verbose + +# Validate the user +$ADUser = Get-ADUser -Identity $SamAccountName +If ($ADUser) { + Write-Output $ADUser + + Write-Verbose -Message "Create CHG request for the work" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New $DomainName Active Directory service account $SamAccountName created - PSU Job Id $PSUJobId"; + Description = "New $DomainName Active Directory service account $SamAccountName created"; + Justification = "New $DomainName Active Directory service account required for zero-trust policies, following guidelines found in KB0016867"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Delete the new user account" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + $CHGNum = $CHG.Number.value + + Write-Verbose -Message ("Completing SNow " + $CHG.Number.value) -Verbose + $CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = ("New $DomainName Active Directory account " + $obj.ADDomain + "\" + $obj.SamAccountName + " created.") + } + Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose + + Write-Verbose -Message "Status Success" -Verbose + $SQLStatus = "Succcess" +} +Else { + Write-Verbose -Message "Status Failure" -Verbose + $SQLStatus = "Failure" +} +#> + +Write-Verbose -Message "Update SQL with that CHG num and update Status" -Verbose +$SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = '$SQLStatus', SNowCHGNum = '$CHGNum' WHERE PSUJobId = " + $PSUJobId) +Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Get-RegistrationList .ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Get-RegistrationList .ps1 new file mode 100644 index 0000000..d06d752 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Get-RegistrationList .ps1 @@ -0,0 +1,3 @@ +Import-Module ITD.Infra-Certificate-External.JsonDB +SET-JDEnvironment -Name prod +select-JDJson -TableName certcache|select CommonName,is_retired,ExpiryDate diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertAutoRenew.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertAutoRenew.ps1 new file mode 100644 index 0000000..29435d6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertAutoRenew.ps1 @@ -0,0 +1,60 @@ +# It all starts with a single line of powershell code. +"I ran at: " + (get-date) +$ENV:USERNAME + +Write-Verbose -Verbose "Import Modules" +#Remove-Module ITD.Infra-Certificate-External.JsonDB +Import-Module ITD.Infra-Certificate-External.JsonDB +Import-Module ITD.Infra-Certificate-External.General -DisableNameChecking + +Write-Verbose -Verbose "Setting Database Environment" +Set-JDEnvironment -Name Prod + + + +Write-Verbose -Verbose "Collect certs up for Renewal" +$certs=Get-ICE-CertUpforRenewal + +Write-Verbose -Verbose "Proccessing Certs" +foreach ($cert in $certs) { + + "Processing: " + $cert.CommonName + Write-Host $cert.CommonName + Write-Host $cert.ParameterSetName + + if ($cert.ParameterSetName -eq "Cloud Service") { + $AppParams = @{ + CommonName = $cert.CommonName + SubjectAlternative = $cert.SubjectAlternative + ApplicationName = $cert.ApplicationName + } + } + elseif ($cert.ParameterSetName -eq "Windows") { + $AppParams = @{ + CommonName = $cert.CommonName + SubjectAlternative = $cert.SubjectAlternative + DestinationServer = $cert.DestinationServer + PfxtoPasswordState = ([System.Convert]::ToBoolean($cert.PfxtoPasswordState)) + } + } + else { + "Param set not defined: " + $cert.CommonName + } + +# Define the script you want to run +$ScriptName = "Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1" + +# Invoke the script and store the job object + + $Job = Invoke-PSUScript -Name $ScriptName -Integrated -Parameters $AppParams +} +#exit + +$job + + + + + + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertificateDeploy.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertificateDeploy.ps1 new file mode 100644 index 0000000..543e132 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Invoke-CertificateDeploy.ps1 @@ -0,0 +1,61 @@ +#Param ( +# $DestinationServer, +# [string]$Email +#) + +$PSUJobId = $UAJob.Id + +Set-JDEnvironment -Name Prod + +$MaintenanceWindow=(Get-ICE-MaintenanceWindow -Credential $Secret:snow_vmcred) + +if ($MaintenanceWindow.ScheduledThisMonth -eq $false) { + Send-ICE-Mail -jobid $PSUJobId -Message "Maintence Window Failed Integraty Check" -Status ActionNeeded -recipientsString fjpeterson@nd.gov +} + +$Day=$MaintenanceWindow + +$Day=$MaintenanceWindow.DaysToChangeWindow +"It is $Day days to Production Maintenance Window." + +if ($MaintenanceWindow.DaysToChangeWindow -eq 10 -and $Hour -eq "18") { #6pm Thursday + $Message="Deploying Cert Changes to Test" + Send-ICE-Mail -jobid $PSUJobId -message $Message -recipientsString fjpeterson@nd.gov + #Idealy we get the oneds that were applied this week have to use date of not before Feild! + + $DestinationServer=(Get-ICE-CertUpforDeploy|Where-Object {$_.Environment -eq "Test"}).DestinationServer + } elseif ($MaintenanceWindow.DaysToChangeWindow -eq 0 -and $Hour -eq "4") { #4am Sunday + $Message="Deploying Cert Changes to Production" + Send-ICE-Mail -jobid $PSUJobId -message $Message -recipientsString fjpeterson@nd.gov + $DestinationServer=(Get-ICE-CertUpforDeploy|Where-Object {$_.Environment -eq "Production"}).DestinationServer + $DestinationServer=$null #Disable prod for now! +} else { + "Skipping - Not time for Production or Test Maintenance" +} + +$Scriptblock = { + $config="C:\ProgramData\ITD\ITD.Infra-Certificate-External.Client\Config\IISBindingConfig.json" + + if (Test-Path $config) { + Update-CCIISCertificateBinding 6>$null 2>&1 + $Configured=$true + } + +$config2="C:\ProgramData\ITD\ITD.Infra-Certificate-External.Client\Config\IISBindingConfig2.json" + if (Test-Path $config2) { + Invoke-CCIISCertificateUpdateFromConfig 6>$null 2>&1 + $Configured=$true + } + +If (!$Configured) { + $hn=(hostname) + "Skipped $hn - Not Configured" + } +} + +ForEach ($ComputerName in $DestinationServer ) { + $results=Invoke-Command -ComputerName $ComputerName -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock $Scriptblock + if ($results -eq $null) { + Send-ICE-Mail -jobid $PSUJobId -message "$ComputerName Binding Not Configured, Will not update website" -recipientsString fjpeterson@nd.gov + } +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-ITDCertificateRequestSectigo.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-ITDCertificateRequestSectigo.ps1 new file mode 100644 index 0000000..edc9ac6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-ITDCertificateRequestSectigo.ps1 @@ -0,0 +1,489 @@ +<# +.SYNOPSIS + Sectigo Certificate Creator +.DESCRIPTION + Creates a Sectigo Certificate for ITD Organization +.NOTES + Requires: + ITD.Infra-Certificate-Internal.Sectigo +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0018128 +#> + +[CmdletBinding()] +param ( + # [Parameter(Mandatory = $true, + # HelpMessage = "CRC TEXT ONLY")] + # [string] + # $CSR, + # [Parameter(Mandatory = $true, + # HelpMessage = "Csr File")] + # [file] + # $CSRfile, + # [Parameter(Mandatory = $true, + # HelpMessage = "Server Type")] + # [ValidateSet('IIS','IIS_OLD','IBM','LINUX','Apache','Tomcat')] + #[string] + #$ServerType="IIS", + + [Parameter(Mandatory = $true, + HelpMessage = "Email address for notifications, comma seperated")] + [string] + $RequesterEmail, + + [Parameter(Mandatory = $true, + HelpMessage = "Common Name for cert")] + [string] + $CommonName, + + [Parameter(Mandatory = $true, + HelpMessage = "Comma separated.")] + [string] + $SubjectAlternative, + [Parameter(Mandatory = $true, + HelpMessage = "Host for Cert Delivery")] + [string] + $DestinationServer + + #[Parameter(Mandatory = $true, + #HelpMessage = "Key Type for cert")] + #[string] + #[ValidateSet("RSA")] + + + + #[Parameter(HelpMessage = "Optional Field, will be appended to standard comments")] + #[string] + #$Comments + + #[Parameter(Mandatory = $true, + # HelpMessage = "File Format")] + #[ValidateSet('x509','x509CO','base64','bin','x509IOR','pem','pemco','pemia','x509R')] + #[string] + #$Format="pem" +) + + +#PSU Reassignment per Zacks standards +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$KeyType="RSA" #reminder this would need to be set on csr. + +#Load Updated Modules +#Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo | Update-Module +#exit + + +#Map script vars to ones that can be Changed for Display Only +$subjAltNames=$SubjectAlternative +$dsvEmail = $RequesterEmail +$myhost=$DestinationServer + +#Set ad Default to Hide from End user. +$ServerType="IIS" +$Format="x509CO" + +#Write-Verbose -Message $Secret:ndgov_svcitdpsuwin.username -Verbose +#Testing Service Now module +#Get-Command Get-ServiceNowRecord + + +#Block access while testing +#if ($RequestedBy -ne 'prvfjpeterson@nd.gov' -and $RequestedBy -ne 'prvnblowers@nd.gov' ) +#{ +# Write-Error "Check with freeman script is currenly disabled" +# exit +#} + +if ($Csrfile){ + $csr= [Text.Encoding]::UTF8.GetString($CSRfile.Content) + } + +Write-Verbose -Message "Validate Email Address" -Verbose +$EmailAddressList = $dsvEmail -split "," + +foreach ($e in $EmailAddressList) { + $user = Get-ADUser -Filter "Mail -eq '$e'" -Properties Mail + $group=Get-ADGroup -Filter "Mail -eq '$($e)'" -Properties Mail + + if ($user -or $group) { + Write-Verbose -Message "$e Passed testing" -Verbose + } + else { + Write-Error "$e is an invalid email address. Terminating Script" + exit + } +} + +Write-Verbose -Message "Validate host" -Verbose + + +$remotehi=Invoke-Command -ComputerName $myhost -ScriptBlock {"hi"} -Credential $Secret:ndgov_svcitdpsuwin + if ($remotehi -eq "hi") { + "Connection to host Succeded" + } else { + "Connection to host failed" + exit + } + +Write-Verbose -Message "Retrieve CI from ServiceNow" -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $IP=(Resolve-DnsName -Name $DestinationServer).IPAddress + $Filter= "ip_address=$ip^operational_status=1" + $Fields=("FQDN","ip_address","Location","model_id","Name","dns_domain","os_domain","Schedule","Environment","sys_class_name","u_nd_application_svc","discovery_source","support_group") + $CI= Get-ITDServiceNowRecord -Table "cmdb_ci_win_server" -Filter $Filter -Fields $Fields -First 1 + + + $ApplicationName=$CI.u_nd_application_svc.display_value + + if (!$ApplicationName) { + write-Error "CI NOT FOUND" + exit + } +$customFields = @( + [pscustomobject]@{ name = "ApplicationName"; value = $ApplicationName } +) +#done validation + +# +# Do the work +# +#> +## Cert REquest +Write-Verbose -Message "Create CSR" -Verbose +$csrScriptBlock={ + +param ($commonName) + +####################### +# Setting the variables +####################### +$UID = [guid]::NewGuid() +$files = @{} +$files['settings'] = "$($env:TEMP)\$($UID)-settings.inf"; +$files['csr'] = "$($env:TEMP)\$($UID)-csr.req" + + + +$request = @{} +$request['SAN'] = @{} + +Write-Host "Provide the Subject details required for the Certificate Signing Request" -ForegroundColor Yellow +$request['CN'] = $commonName +$request['O'] = "NDIT" +$request['OU'] = "State Of North Dakota" +$request['L'] = "Bismarck" +$request['S'] = "ND" +$request['C'] = "US" + + +######################### +# Create the settings.inf +######################### +$settingsInf = " +[Version] +Signature=`"`$Windows NT`$ +[NewRequest] +KeyLength = 2048 +Exportable = TRUE +MachineKeySet = TRUE +SMIME = FALSE +RequestType = PKCS10 +ProviderName = `"Microsoft RSA SChannel Cryptographic Provider`" +ProviderType = 12 +HashAlgorithm = sha256 +;Variables +Subject = `"CN={{CN}},OU={{OU}},O={{O}},L={{L}},S={{S}},C={{C}}`" +[Extensions] +{{SAN}} +;Certreq info +;http://technet.microsoft.com/en-us/library/dn296456.aspx +;CSR Decoder +;https://certlogik.com/decoder/ +;https://ssltools.websecurity.symantec.com/checker/views/csrCheck.jsp +" + +$request['SAN_string'] = & { + if ($request['SAN'].Count -gt 0) { + $san = "2.5.29.17 = `"{text}`" +" + Foreach ($sanItem In $request['SAN'].Values) { + $san += "_continue_ = `"dns="+$sanItem+"&`" +" + } + return $san + } +} + +$settingsInf = $settingsInf.Replace("{{CN}}",$request['CN']).Replace("{{O}}",$request['O']).Replace("{{OU}}",$request['OU']).Replace("{{L}}",$request['L']).Replace("{{S}}",$request['S']).Replace("{{C}}",$request['C']).Replace("{{SAN}}",$request['SAN_string']) + +# Save settings to file in temp +$settingsInf > $files['settings'] + +# Done, we can start with the CSR +#Clear-Host + +################################# +# CSR TIME +################################# + +# Display summary +Write-Host "Certificate information +Common name: $($request['CN']) +Organisation: $($request['O']) +Organisational unit: $($request['OU']) +City: $($request['L']) +State: $($request['S']) +Country: $($request['C']) +Subject alternative name(s): $($request['SAN'].Values -join ", ") +Signature algorithm: SHA256 +Key algorithm: RSA +Key size: 2048 +" -ForegroundColor Yellow + +certreq -new $files['settings'] $files['csr'] > $null + +# Output the CSR +$CSR = Get-Content $files['csr'] +$CSR|Out-String +} #end of script block + +#myhost is used as cn +$csr=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock $csrScriptBlock -ArgumentList $commonName + + +#Write-Verbose -Message "Validate CSR" -Verbose +#$TestResults=Test-SectigoCertificateRequest -csr $csr + +#If ($TestResults.Valid -eq $True) { +# Write-Verbose -Message "CSR Passed Testing" -Verbose +#} +#else { +# Write-Error "You don't have a valid csr. Terminating Script" +# "CSR Content " + $csr +# exit +#} +# End of Creating csr + + +## +$Comments="Enrolled by PSUniversal, Job " + $UAJob.Id + ", User " + $UAJob.Identity.Name + "," + $Comments +$Comments + +if ($ApplicationName) +{ +$customFields = @( + @{ + name = "ApplicationName" + value = $ApplicationName + } +) +} + +Write-Verbose -Message "Setting up params for Enroll-SectigoCertificateRequest" -Verbose + +$splat = @{ + Csr=$csr + dcvEmail=$dsvEmail + Comment=$Comments + KeyType=$KeyType + subjAltNames=$subjAltNames +} + +$b1 = @{ + customFields = $customFields +} + +if ($customFields) { + $splat = $splat+ $b1 +} + + +#$splat2=@{ +# subjAltName=$subjAltName +#} + +#if ( $subjAltName) { +# $Splat = $splat + $splat2 +#} + +$cred=$Secret:SectigoClientSecret +$env:Sectigoclientid = $cred.UserName +$env:SectigoclientSecret = $cred.GetNetworkCredential().Password + + +#get-command -Module ITD.Infra-Certificate-Internal.Sectigo +#remove-module ITD.Infra-Certificate-Internal.Sectigo +Write-Verbose -Message "Enroll-SectigoCertificateRequest" -Verbose +Get-SectigoApiToken + + +$certRequest = Enroll-SectigoCertificateRequest @Splat + + +#seems to be issue with this requiring addtional wait time. +Write-Verbose -Message "Waiting for Cert Status" -Verbose + +while ($certstatus -ne "Issued") { + $certstatus=(Get-SectigoCertificate -OrderId $certRequest.sslid).status + Sleep 1 + $run= $run + 1 + if ($run -gt 60) { + Write-Error "Failed to get issue status after 1 minute..exiting" + exit + } +} + + +$tp=(Get-SectigoCertificate -OrderId $certRequest.sslid).sha1Hash +"tp: $tp" + +Write-Verbose -Message "Downloading interm Certificate" -Verbose + +$IntermCertRootPath="c:\psautocerts_interm\" + +mkdir $IntermCertRootPath 2>$null + +$IntermCertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format x509IOR -CertRootPath $IntermCertRootPath).FullName +ls $IntermCertPath |select FullName, LastWriteTime, Length + + +Write-Verbose -Message "Downloading Certificate" -Verbose + +$CertRootPath="c:\psautocerts\" +mkdir $CertRootPath 2>$null +$CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format $Format -CertRootPath $CertRootPath).FullName +ls $CertPath |select FullName, LastWriteTime, Length + + + +# Define source and destination paths +$remoteCertPath = "C:\Temp\CertificateX.cer" # A temporary location on the remote machine +$IntermremoteCertPath = "C:\Temp\Interm_CertificateX.cer" + +# Copy the interm certificate file to the remote machine +Copy-Item -Path $IntermCertPath -Destination $IntermremoteCertPath -ToSession (New-PSSession -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin) + + +# Copy the certificate file to the remote machine +Copy-Item -Path $CertPath -Destination $remoteCertPath -ToSession (New-PSSession -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin) + + +# Define parameters for importing the certificate + +#$certPassword = "YourCertPassword" | ConvertTo-SecureString -AsPlainText -Force # If it's a PFX with a password + +$IntermcertStoreLocation = "Cert:\LocalMachine\Root" + +$Intermcertimport=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock { + param($IntermremoteCertPath, $IntermcertStoreLocation ) + "Import-Certificate -FilePath -CertStoreLocation $IntermcertStoreLocation" + Import-Certificate -FilePath $IntermremoteCertPath -CertStoreLocation $IntermcertStoreLocation + if (Test-Path -Path $IntermremoteCertPath -PathType Leaf) { + Remove-Item -Path $IntermremoteCertPath -Force -Confirm:$false 2>$null + } + # Import the certificate + +} -ArgumentList $IntermremoteCertPath, $IntermcertStoreLocation + +if ($Intermcertimport.Thumbprint ) { + Write-Verbose -verbose "Successful Import." + $IntermThumbprint=$Intermcertimport.Thumbprint + Write-Verbose "Thumbprint: $IntermThumbprint" + + if (Test-Path -Path $CertPath -PathType Leaf) { + Remove-Item -Path $IntermCertPath -Force -Confirm:$false + Write-Host "File '$IntermCertPath' deleted successfully." + } else { + Write-Host "Path '$IntermCertPath' does not exist or is not a file." + } +} + +################## +$certStoreLocation = "Cert:\LocalMachine\My" + +$certimport=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock { + param($remoteCertPath, $certStoreLocation,$CommonName ) + "Import-Certificate -FilePath $remoteCertPath -CertStoreLocation $certStoreLocation" + # Import the certificate + $cert=Import-Certificate -FilePath $remoteCertPath -CertStoreLocation $certStoreLocation + $mydate=Get-Date -Format 'yyyy-MM-dd'|out-string + $FriendlyName = $CommonName + "-" +$myDate + $cert.FriendlyName = $FriendlyName + if (Test-Path -Path $remoteCertPath -PathType Leaf) { + Remove-Item -Path $remoteCertPath -Force -Confirm:$false 2>$null + } + $cert +} -ArgumentList $remoteCertPath, $certStoreLocation,$CommonName + + +if ($certimport.Thumbprint ) { + Write-Verbose -verbose "Successful Import." + $Thumbprint=$certimport.Thumbprint + Write-Verbose "Thumbprint: $Thumbprint" -Verbose + + if (Test-Path -Path $CertPath -PathType Leaf) { + Remove-Item -Path $CertPath -Force -Confirm:$false + Write-Host "File '$CertPath' deleted successfully." + } else { + Write-Host "Path '$CertPath' does not exist or is not a file." + } +} + +# +# Request Work +# + +# Validate the user +$StartDateTime = (Get-Date) +$EndDateTime = $StartDateTime.AddMinutes(1) +$RequestedBy=$UAJob.Identity.Name + +#$ServiceNowEnvironment = "TEST" +#TemplateName = 'NDIT-SPS-Ansible Automation Platform' +if ($certimport.Thumbprint ) { + + Write-Verbose -Message "Create CHG request for the work" -Verbose + $ServiceNowEnvironment = "Production" #'Production', 'Test', 'Development' + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-PSU Cert Automation Platform' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New Certificate Created - PSU Job Id $PSUJobId"; + Description = "New Certificate Created - PSU Job Id $PSUJobId"; + Justification = "Security Standards require an updated certificate"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Revoke Cert" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + $CHGNum = $CHG.Number.value + + Write-Verbose -Message ("Completing Snow " + $CHG.Number.value) -Verbose + $CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = ("New Certificate" + $obj.ADDomain + "\" + $obj.SamAccountName + " created.") + } + Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose + + Write-Verbose -Message "Status Success" -Verbose + $SQLStatus = "Succcess" +} +Else { + Write-Verbose -Message "Status Failure" -Verbose + $SQLStatus = "Failure" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1 new file mode 100644 index 0000000..25347d3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1 @@ -0,0 +1,426 @@ + + + +<# +.SYNOPSIS + Sectigo Certificate Creator +.DESCRIPTION + Creates a Sectigo Certificate for ITD Organization +.NOTES + Requires: + ITD.Infra-Certificate-Internal.Sectigo +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0018128 +#> + +[CmdletBinding(DefaultParameterSetName = 'Windows')] +param( + # Email address for notifications, comma seperated +# [Parameter(Mandatory, ParameterSetName = 'Windows')] +# [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] +# [String]$RequesterEmail, + + # Common Name for cert + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] + [String]$CommonName, + + # Comma separated. + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] + [String]$SubjectAlternative, + + # Host for Cert Delivery, comma seperated + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [String]$DestinationServer, + + # Option for pfx in PasswordState + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [bool]$PfxtoPasswordState, + + # AppName CI in CMDB + [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] + [String]$ApplicationName +) + + +process { + + + #Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-External.General|Update-Module -Scope CurrentUser + #exit + Import-Module ITD.Infra-Certificate-External.General -DisableNameChecking + Import-Module ITD.Infra-Certificate-External.JsonDB + + + #We reusing and breaking it up to an array for further use in script + $DestinationServerArray = $DestinationServer -split "," + + #PSU Reassignment per Zacks standards + $RequestedBy = $UAJob.Identity.Name # user that started the job + $PSUJobId = $UAJob.Id + + + #$Test Mode + # - Blocks Access to selected users + # - Uses Test Environment for ServiceNow Change + # - Variable can be used for debugging + $ApprovedTester=@('prvfjpeterson@nd.gov','prvjdkieson@nd.gov') + + if ($test) { + Write-Verbose -Message "Running in Test Mode " -Verbose + if ($ApprovedTester -contains $RequestedBy) + { + "You are allowed but others are disabled" + } + else { + Write-Error "Check with freeman script is currenly disabled" + # exit + } + } + + #Set ad Default to Hide from End user. + $ServerType="IIS" + $Format="base64" + $KeyType="RSA" #reminder this would need to be set on csr. + $mydate=(Get-Date -Format 'yyyy-MM-dd'|out-string).Trim() + $FriendlyName = $CommonName + "-" +$myDate + + #Write-Verbose -Message "Update Module" -Verbose + #Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-External.Sectigo |Update-Module -Scope AllUsers + + + if ($PSCmdlet.ParameterSetName -eq 'Windows') { + Write-Verbose -Message "Validate host" -Verbose + Foreach ($ComputerName in $DestinationServerArray) { + $remotehi=Invoke-Command -ComputerName $ComputerName -ScriptBlock {"hi"} -Credential $Secret:ndgov_svcitdpsuwin + + if ($remotehi -eq "hi") { + "Connection to host $ComputerName Succeded" + } else { + "Connection to host $ComputerName failed" + exit + } + } + } + + if ($PSCmdlet.ParameterSetName -eq 'Windows') { + Write-Verbose -Message "Retrieve CI from ServiceNow" -Verbose + #We are just pulling appname from first DestinationServer + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $IP=(Resolve-DnsName -Name $DestinationServerArray[0]).IPAddress + $Filter= "ip_address=$ip^operational_status=1" + $Fields=("FQDN","ip_address","Location","model_id","Name","dns_domain","os_domain","Schedule","Environment","sys_class_name","u_nd_application_svc","discovery_source","support_group") + $CI= Get-ITDServiceNowRecord -Table "cmdb_ci_win_server" -Filter $Filter -Fields $Fields -First 1 + $ApplicationName=$CI.u_nd_application_svc.display_value + + if (!$ApplicationName) { + write-Error "CI NOT FOUND" + exit + } + $customFields = @( + [pscustomobject]@{ name = "ApplicationName"; value = $ApplicationName } + ) + } + else { #ParmeterSet Not Windows + Write-Verbose -Message "Retrieve App record from ServiceNow" -Verbose + + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $Filter= "name=$ApplicationName" + $Fields=("name") + $CI= Get-ITDServiceNowRecord -Table "cmdb_ci_service_auto" -Filter $Filter -Fields $Fields + + if ($CI.name.value -ne $ApplicationName ) { + Write-Error "Could not find $ApplicationName" + exit + } + } + + +#Got email address now! +$RequesterEmail=Get-ICE-Snowemail -ApplicationName $ApplicationName -Credential $Secret:snow_vmcred + + Send-ICE-Mail -recipientsString $RequesterEmail -Jobid $PSUJobId -status "Started" -Message "Check job status" + + + + + + + + Write-Verbose -Message "Validate Email Address" -Verbose + $EmailAddressList = $RequesterEmail -split "," + + + foreach ($e in $EmailAddressList) { + $user = Get-ADUser -Filter "Mail -eq '$e'" -Properties Mail + $group = Get-ADGroup -Filter "Mail -eq '$($e)'" -Properties Mail + + if ($user -or $group) { + Write-Verbose -Message "$e Passed testing" -Verbose + } + else { + Write-Error "$e is an invalid email address. Terminating Script" + exit + } + } + + $RequesterEmail=Get-ICE-Snowemail -ApplicationName $ApplicationName -Credential $Secret:snow_vmcred + + +#Set env prod +Set-JDEnvironment -Name prod + + +Write-Verbose -Verbose "Retire PreviousThumbprint" +$PreviousThumbprint=(Select-JDJson -TableName certcache -CommonName $commonname).Thumbprint + +if ($PreviousThumbprint) { + $table=@("certlog","certcache") + Foreach ($t in $table) { + Set-JDJson -TableName $t ` + -Where { param($row) $row.CommonName -eq $commonname } ` + -Set @{ is_retired = $true; PreviousThumbprint = $PreviousThumbprint } ` + -Verbose + } #end of foreach +} #end of if $Previous thumbprint + + # Done validation + + # + # Do the work + # + # + + Write-Verbose -Message "Create CSR" -Verbose + $csr = New-ICE-CSR -commonName $commonName + + Write-Verbose -Message "Test CSR" -Verbose + + If (Test-ICE-CSR -csrstring $csr) { + "CSR Passed" + } + else { + Write-Error "Not A Valid CSR" + } + + $Comments="Enrolled by PSUniversal, Job " + $UAJob.Id + ", User " + $UAJob.Identity.Name + "," + $Comments + + if ($ApplicationName) + { + $customFields = @( + @{ + name = "ApplicationName" + value = $ApplicationName + } + ) + } + + Write-Verbose -Message "Setting up params for Enroll-SectigoCertificateRequest" -Verbose + + $splat = @{ + Csr=$csr + dcvEmail=$RequesterEmail + Comment=$Comments + KeyType=$KeyType + subjAltNames=$SubjectAlternative + } + + $b1 = @{ + customFields = $customFields + } + + if ($customFields) { + $splat = $splat+ $b1 + } + + $cred=$Secret:SectigoClientSecret + $env:Sectigoclientid = $cred.UserName + $env:SectigoclientSecret = $cred.GetNetworkCredential().Password + + Write-Verbose -Message "Enroll-SectigoCertificateRequest" -Verbose + Get-SectigoApiToken + + $certRequest = Enroll-SectigoCertificateRequest @Splat + + Write-Verbose -Message "Waiting for Cert Status" -Verbose + + while ($certstatus -ne "Issued") { + $certstatus=(Get-SectigoCertificate -OrderId $certRequest.sslid).status + Sleep 1 + $run= $run + 1 + if ($run -gt 60) { + Write-Error "Failed to get issue status after 1 minute..exiting" + exit + } + } + + Write-Verbose -Message "Downloading Certificate" -Verbose + + $CertRootPath="c:\psautocerts\" + mkdir $CertRootPath 2>$null + + $CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format $Format -CertRootPath $CertRootPath).FullName + + Write-Verbose -Message "Generate Password" -Verbose + + $pfxPassword= Generate-ICE-PFXPassword + $secure_pfxpassword = ConvertTo-SecureString $pfxPassword -AsPlainText -Force + $pfxCredential = [System.Management.Automation.PSCredential]::new("None", $secure_pfxpassword) + + Write-Verbose -Verbose "Convert to pfx" + + $results=Convert-ICE-PKS7toPfx -CertFile $CertPath -pfxCredential $pfxCredential + $pfxPath=$results.Fullname + + Write-Verbose -Verbose "Load the certificate object" + + $collection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $collection.Import($pfxPath, $pfxPassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet) + # Display all certificates in the chain + #$collection | Format-List Subject, Issuer, Thumbprint, NotAfter + $foundCerts = $collection.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindBySubjectName, $CommonName, $false) + $ExpiryDate = $foundCerts[0].NotAfter + $Thumbprint=$foundCerts[0].Thumbprint + + if ($PSCmdlet.ParameterSetName -eq 'Cloud Service') { + $PfxtoPasswordState=$True + } + + if ($PfxtoPasswordState) { + Write-Verbose -Verbose "Save to Password State" + + + $PasswordStateParams = @{ + Title = $FriendlyName; + Description = $Comments ; + ExpiryDate = $ExpiryDate ; + APICreds = $Secret:pwdvault_WindowsCertificates ; + pfxCredential = $pfxCredential; + PfxPath = $pfxPath; + } + + $PasswordStateSuccess=Send-ICE-PfxtoPasswordState @PasswordStateParams + } + + #Send file to cert store windows only" + if ($PSCmdlet.ParameterSetName -eq 'Windows') { + $CertificatetoCertStore = @{ + pfxPath = $pfxPath; + RemoteCertPath = "c:\temp\certificatex.pfx"; + DestinationServer = $DestinationServerArray + Credential = $Secret:ndgov_svcitdpsuwin ; + pfxCredential = $pfxCredential; + CertStoreLocation = "Cert:\LocalMachine\MY"; + ThumbPrint = $ThumbPrint ; + FriendlyName = $FriendlyName + } + + $CertStoreResults=Send-ICE-CertificatetoCertStore @CertificatetoCertStore + $CertStoreResults + } + + Write-Verbose -Verbose "Cleaning Up Temp Files" + if (Test-Path -Path $CertPath -PathType Leaf) { + Remove-Item -Path $CertPath -Force -Confirm:$false 2>$null + } + + if (Test-Path -Path $pfxPath -PathType Leaf) { + Remove-Item -Path $pfxPath -Force -Confirm:$false 2>$null + } + + # Validate the user + $StartDateTime = (Get-Date) + $EndDateTime = $StartDateTime.AddMinutes(1) + $RequestedBy=$UAJob.Identity.Name + + if ($PSCmdlet.ParameterSetName -eq 'Cloud Service' -and $PasswordStateSuccess -eq $True ) { $Completed=$true} + if ($PSCmdlet.ParameterSetName -eq 'Windows' -and $CertStoreResults.Success -eq $True) { $Completed=$true} + + + if ($Completed) { + Write-Verbose -Message "Create CHG request for the work" -Verbose + $ServiceNowEnvironment = "Production" #'Production', 'Test', 'Development' + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-PSU Cert Automation Platform' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New Certificate Created - PSU Job Id $PSUJobId"; + Description = "New Certificate Created - PSU Job Id $PSUJobId"; + Justification = "Security Standards require an updated certificate"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Revoke Cert" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + $CHGNum = $CHG.Number.value + + Write-Verbose -Message ("Completing Snow " + $CHG.Number.value) -Verbose + $CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = ("New Certificate" + $obj.ADDomain + "\" + $obj.SamAccountName + " created.") + } + Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose + + Write-Verbose -Message "Status Success" -Verbose + $Jobstatus = "Success" + + } + Else { + Write-Verbose -Message "Status Failure" -Verbose + $JobStatus = "Failure" + + } + +Send-ICE-Mail -recipientsString $RequesterEmail -Jobid $PSUJobId -status $Jobstatus -Message "Created Standard Change" + + + +$log_psobject=[pscustomobject]@{ + Timestamp = (Get-Date) + ParameterSetName = $ParameterSetName + RequestedBy = $RequestedBy + RequesterEmail = $RequesterEmail + CommonName = $CommonName + SubjectAlternative = $SubjectAlternative + DestinationServer = $DestinationServer + PfxtoPasswordState = $PfxtoPasswordState + ApplicationName = $ApplicationName + ExpiryDate = $ExpiryDate + Thumbprint = $Thumbprint + PreviousThumbprint = $PreviousThumbprint + is_retired = $false + } + + Write-Verbose -Verbose "Log new transaction to both tables. " +#Cache table common name is the primary key so there should only be an update? + + $table=@("certlog","certcache") + Foreach ($t in $table) { + $log_psobject| Add-JDJson -TableName $t -Verbose + } + + + + + + + ########################################### + if ($PasswordStateSuccess) { + "Your new Certificate is in PasswordState at: " + " Windows/Certificates/${FriendlyName}" + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Register-CommonName.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Register-CommonName.ps1 new file mode 100644 index 0000000..63ca067 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Register-CommonName.ps1 @@ -0,0 +1,168 @@ +[CmdletBinding(DefaultParameterSetName = 'Windows')] +param( + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] + [String]$CommonName, + + # Host for Cert Delivery, comma seperated + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [String]$DestinationServer, + + # Option for pfx in PasswordState + [Parameter(Mandatory, ParameterSetName = 'Windows')] + [bool]$PfxtoPasswordState, + + # AppName CI in CMDB + [Parameter(Mandatory, ParameterSetName = 'Cloud Service')] + [String]$ApplicationName +) + #PSU Reassignment per Zacks standards + $RequestedBy = $UAJob.Identity.Name # user that started the job + $PSUJobId = $UAJob.Id + + +$DestinationServerArray = $DestinationServer -split "," + if ($PSCmdlet.ParameterSetName -eq 'Windows') { + Write-Verbose -Message "Validate host" -Verbose + Foreach ($ComputerName in $DestinationServerArray) { + $remotehi=Invoke-Command -ComputerName $ComputerName -ScriptBlock {"hi"} -Credential $Secret:ndgov_svcitdpsuwin + + if ($remotehi -eq "hi") { + "Connection to host $ComputerName Succeded" + } else { + "Connection to host $ComputerName failed" + exit + } + } + } + + if ($PSCmdlet.ParameterSetName -eq 'Windows') { + Write-Verbose -Message "Retrieve CI from ServiceNow" -Verbose + #We are just pulling appname from first DestinationServer + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $IP=(Resolve-DnsName -Name $DestinationServerArray[0]).IPAddress + $Filter= "ip_address=$ip^operational_status=1" + $Fields=("FQDN","ip_address","Location","model_id","Name","dns_domain","os_domain","Schedule","environment","sys_class_name","u_nd_application_svc","discovery_source","support_group") + $CI= Get-ITDServiceNowRecord -Table "cmdb_ci_win_server" -Filter $Filter -Fields $Fields -First 1 + $ApplicationName=$CI.u_nd_application_svc.display_value + + if (!$ApplicationName) { + write-Error "CI NOT FOUND" + exit + } + $customFields = @( + [pscustomobject]@{ name = "ApplicationName"; value = $ApplicationName } + ) + } + else { #ParmeterSet Not Windows + Write-Verbose -Message "Retrieve App record from ServiceNow" -Verbose + + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $Filter= "name=$ApplicationName" + $Fields=("name") + $CI= Get-ITDServiceNowRecord -Table "cmdb_ci_service_auto" -Filter $Filter -Fields $Fields + + if ($CI.name.value -ne $ApplicationName ) { + Write-Error "Could not find $ApplicationName" + exit + } + } + + Write-Verbose -Message "Validate Email Address" -Verbose + + + $RequesterEmail=Get-ICE-Snowemail -ApplicationName $ApplicationName -Credential $Secret:snow_vmcred + $EmailAddressList = $RequesterEmail -split "," + + foreach ($e in $EmailAddressList) { + $user = Get-ADUser -Filter "Mail -eq '$e'" -Properties Mail + $group = Get-ADGroup -Filter "Mail -eq '$($e)'" -Properties Mail + + if ($user -or $group) { + Write-Verbose -Message "$e Passed testing" -Verbose + } + else { + Write-Error "$e is an invalid email address. Terminating Script" + exit + } + } + + + + +#Set env prod + +Write-Verbose -Verbose "Set DB Environment" +Set-JDEnvironment -Name prod + + +Write-Verbose -Verbose "Remoting to other server to get cert info" + + +$ComputerName=$DestinationServerArray[0] +$OldCert=Get-ICE-RemoteCertInfo -ComputerName $ComputerName -CommonName $CommonName -Credential $Secret:ndgov_svcitdpsuwin + +Write-Verbose -Verbose "Old Cert" +$OldCert|fl + + +$ExpiryDate=$OldCert.NotAfter +$subjectAlternative = $OldCertsubjectAlternative +$ParameterSetName=$PSCmdlet.ParameterSetName +$SubjectAlternative = $OldCert.subjectAlternative +$ExpiryDate = $OldCert.NotAfter +$Thumbprint=$OldCert.Thumbprint +$PreviousThumbprint = $false + + + +Write-Verbose -Verbose "Create Powershell object for Logging" +$log_psobject=[pscustomobject]@{ + Timestamp = (Get-Date) + ParameterSetName = $ParameterSetName + RequestedBy = $RequestedBy + RequesterEmail = $RequesterEmail + CommonName = $CommonName + Environment = $CI.environment.value + NotBefore = $OldCert.NotBefore + SubjectAlternative = $SubjectAlternative + DestinationServer = $DestinationServer + PfxtoPasswordState = $PfxtoPasswordState + ApplicationName = $ApplicationName + ExpiryDate = $ExpiryDate + Thumbprint = $Thumbprint + PreviousThumbprint = $PreviousThumbprint + is_retired = $false + } + + +$bla=$log_psobject|Out-String + +Write-Host $bla + +#$Result = Read-Host "Does this information look correct y/n" +$Result = "y" #forcing + + + +if ($result -eq "y") { + Write-Verbose -Verbose "Log new transaction to both tables. " + #Cache table common name is the primary key so there should only be an update? + $table=@("certlog","certcache") + Foreach ($t in $table) { + $log_psobject| Add-JDJson -TableName $t -Verbose + } +} +else { +"Did not Save! You are NOT Registered!" +} + +Write-Verbose -Verbose "Installing Client Module" + $InstallParams= @{ + DestinationServer = $DestinationServer + Email = $RequesterEmail + PSUJobId = $PSUJobId + Credential = $Secret:ndgov_svcitdpsuwin + } + +Install-ICE-Client @InstallParams \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Troubleshooting.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Troubleshooting.ps1 new file mode 100644 index 0000000..e12dad0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Troubleshooting.ps1 @@ -0,0 +1,17 @@ + +#Get-MaintenanceWindow -Credential $Secret:snow_vmcred + +Param ( + $DestinationServer +) + +$Scriptblock = { + $config="C:\scripts\ITD.Infra-Certificate-External.Client\Data\IISBindingAutoConfig.config" + Test-Path $config +} + +ForEach ($ComputerName in $DestinationServer ) { + $result=Invoke-Command -ComputerName $ComputerName -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock $Scriptblock + $computername + ":" + $result +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Unregister-CommonName.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Unregister-CommonName.ps1 new file mode 100644 index 0000000..fd01a25 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Unregister-CommonName.ps1 @@ -0,0 +1,27 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, + HelpMessage = "Common Name for cert")] + [string] + $CommonName +) +Import-Module ITD.Infra-Certificate-External.JsonDB + +Write-Verbose -Verbose "Set DB Environment" +Set-JDEnvironment -Name prod + +$PreviousThumbprint=(Select-JDJson -TableName certcache -CommonName $commonname).Thumbprint + +#Unreg from cert log +if ($PreviousThumbprint) { + $table=@("certlog") + Foreach ($t in $table) { + Set-JDJson -TableName $t ` + -Where { param($row) $row.CommonName -eq $commonname } ` + -Set @{ is_retired = $true; PreviousThumbprint = 'OLD-000-XYZ' } ` + -Verbose + } #end of foreach +} #end of if $Previous thumbprint + +#delete from certcache +Remove-JDJson -TableName certcache -Where { param($o) $o.commonname -eq $commonname } diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Update-Client.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Update-Client.ps1 new file mode 100644 index 0000000..100be65 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/Update-Client.ps1 @@ -0,0 +1,17 @@ + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + $DestinationServer, + $Email +) +$PSUJobId = $UAJob.Id + + $InstallParams= @{ + DestinationServer = $DestinationServer + Email = $Email + PSUJobId = $PSUJobId + Credential = $Secret:ndgov_svcitdpsuwin + } + +Install-ICE-Client @InstallParams diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 new file mode 100644 index 0000000..93b5ae6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 @@ -0,0 +1,31 @@ +Param( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName = $null, + + [ValidateSet('All Day Every Day', + 'Weekdays 700 to 1800', + 'All Week 500 to 2300' + )] + [string] + $SupportHours + +) + +$Func = { + param($C, $SwSupportHours) + Write-Verbose -Message "Add to Solarwinds" -Verbose + Import-SWDiscovery -ComputerName $C -Integration ServiceNow + + Start-Sleep -Seconds 10 + + Write-Verbose -Message "Set Solarwinds node custom properties if parameter exists" -Verbose + If($PSBoundParameters.ContainsKey('SupportHours')){ + Write-Verbose -Message "SupportHours $SwSupportHours." -Verbose + Set-SWNodeCustomProperty -ComputerName $C -Property SupportHours -Value $SwSupportHours + } +} + +$ComputerName | ForEach-Object { + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $_,$SupportHours -Credential $Secret:ndgov_svcitdiaasauto +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 new file mode 100644 index 0000000..54e5035 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 @@ -0,0 +1,10 @@ +Param( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName = $null +) + +ForEach ($cn in $ComputerName) { + Write-Verbose -Message "Attempt Solarwinds removal for $cn" -Verbose + Remove-ITDSolarwindsNode -ComputerName $cn -Credential $Secret:ndgov_svcitdiaasauto -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 new file mode 100644 index 0000000..6b82563 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 @@ -0,0 +1,38 @@ +Write-Verbose -Message "Prepare variables based on PSU server" -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServiceNowEnvironment = "Test" + } + "ITDWINAUTOP1" { + $ServiceNowEnvironment = "Production" + } +} +New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + +<# +Write-Verbose -Message "Retrieve List of all Server Build Request request items from ServiceNow where closed_at is Yesterday and request_type is Change" -Verbose +$Filter = 'cat_item=c64e27af47244610b7853238436d435d^variables.3bf9fc3b47240a10b7853238436d430b=Change^closed_atONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()' +####### 'cat_item=c64e27af47244610b7853238436d435d^variables.3bf9fc3b47240a10b7853238436d430b=Change^closed_atONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()' +$CompletedRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter + +Write-Verbose -Message ("Found " + @($CompletedRitms).count + " completed Ritms.") +#> + +$CompletedRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number RITM0269022 +ForEach($Ritm in $CompletedRITMs){ + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number ($Ritm.number.value) -IncludeCustomVariable -IncludeVariableSet + # loop each VM row + ForEach($row in $Ritm.VariableSet){ + # resolve sys_id to host name + $CmdbCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId $row.host_name_ref + Write-Verbose -Message ("Start " + $Ritm.number.value + " server " + $row.host_name_ref + ', ' + $CmdbCi.fqdn.display_value) -Verbose + + # run solarwinds import + $Func = { + param ($c) + Write-Verbose -Message "Attempting to import $c to Solarwinds" + Import-SWDiscovery -ComputerName $c + } + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $CmdbCi.fqdn.display_value -Credential $Secret:ndgov_svcitdiaasauto + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 new file mode 100644 index 0000000..e57d0f7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 @@ -0,0 +1,36 @@ +Param( + [string] + $Name, + + [ValidateSet( + 'Infra-ActiveDirectory.Object', + 'Infra-Azure.VirtualMachine', + 'Infra-Certificate-External.Sectigo', + 'Infra-Monitoring-Solarwinds', + 'Infra-VMware.Administration', + 'Infra-VMware.VirtualMachine', + 'Infra-VMware.Snapshot', + 'ITD-WindowsServer.FileManagement', + 'ITD-WindowsServer.General', + 'ITD-WindowsServer.Lifecycle', + 'Shared-Powerschool' + )] + [string] + $Path +) + +switch ($Path){ + <# example switch condition and actions + { $_ -like "App-XXXXX"} {$TagNamesEnforced = @('Shared-XXXXX_Modify)} + #> + { $_ -eq "Infra-ActiveDirectory.Object" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Infra-Azure.*"} {$TagNamesEnforced = @('Infra-VMware_Modify')} + { $_ -like "Infra-Monitoring-Solarwinds*" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Infra-Certificate-External.Sectigo*" } { $TagNamesEnforced = @('Infra-Certificate_Modify') } + { $_ -like "Infra-VMware*" } { $TagNamesEnforced = @('Infra-VMware_Modify') } + { $_ -like "ITD-WindowsServer*" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Shared-PowerSchool*" } { $TagNamesEnforced = @('Shared-PowerSchool_Modify') } + +} +New-PSUScript -Name $Name -Path "$Path\$Name" -Tag @($TagNamesEnforced) -ScriptBlock {# It all starts with a single line of powershell code. +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 new file mode 100644 index 0000000..e6e7554 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 @@ -0,0 +1,42 @@ +####### +Write-Verbose -Message "Determine if ITD_PwshGallery is registered" -Verbose +If(Get-PSRepository -Name ITD_PwshGallery -ErrorAction SilentlyContinue){ + Write-Verbose -Message "ITD_PwshGallery found." -Verbose +} Else { + $RegisterPSRepositoryParams = @{ + Name = 'ITD_PwshGallery'; + InstallationPolicy = 'Trusted'; + SourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + PublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptSourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptPublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + } + Register-PSRepository @RegisterPSRepositoryParams +} + +Write-Verbose -Message "Retrieve list of all available modules and versions" +$ITDModules = Find-Module -Name "ITD.*" -Repository ITD_PwshGallery + + +Write-Verbose -Message "Compare local module versions to repository versions, and update if needed" +ForEach($ITDModule in $ITDModules){ + $VersionsAvailable = $null + $MostRecentVersion = $null + $RepoVersion = $null + + $VersionsAvailable = Get-Module -Name $ITDModule.name -ListAvailable + $MostRecentVersion = $VersionsAvailable | Sort-Object Version -Descending | Select -First 1 + $RepoVersion = $ITDModule.Version + + If($null -eq $MostRecentVersion) { + Write-Verbose -Message ($ITDModule.Name + " was not found locally, installing module now.") -Verbose + Install-Module -Name $ITDModule.Name -Scope AllUsers -Repository ITD_PwshGallery + } Else { + Write-Verbose -Message ($ITDModule.Name + " was found locally, comparing versions and updating if needed..") -Verbose + Write-Host -Message ($ITDModule.Name) + Write-Host -Message ("Local version is " + $MostRecentVersion.Version) + Write-Host -Message ("The Repo version is " + $RepoVersion) + Write-Host -Message ("") + Update-Module -Name $ITDModule.Name -Scope AllUsers -Verbose + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 new file mode 100644 index 0000000..e035ea3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 @@ -0,0 +1 @@ +# It all starts with a single line of powershell code. \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 new file mode 100644 index 0000000..2c52aa5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 @@ -0,0 +1,131 @@ +<# +.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 +#> + + + +<# Scheduled Task metadata +General + Get IPs for PA + run as ndgov\!itdvcenterppa + run whether user is logged on or not + Triggers + Daily, 11am + Daily, 11pm +Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1" + new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetVMwareVMGuestIPsForPA\GetVMwareVMGuestIPsForPA.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + +#Connect +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + + +##Windows + + +#Output File +$OutFileWin = "c:\inetpub\wwwroot\Win.txt" +#$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileWin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Win\$Timestamp-Win.txt" +Remove-Item $OutFileWin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "windows7Guest" ` + -or $_.GuestID -eq "windows7_64Guest" ` + -or $_.GuestID -eq "windows7Server64Guest" ` + -or $_.GuestID -eq "windows8_64Guest" ` + -or $_.GuestID -eq "windows8Server64Guest" ` + -or $_.GuestID -eq "windows9Server64Guest" ` + -or $_.GuestID -eq "winLonghorn64Guest" ` + -or $_.GuestID -eq "winLonghornGuest" ` + -or $_.GuestID -eq "winNetStandardGuest" ` + -or $_.GuestID -eq "winNetEnterpriseGuest" ` + -or $_.GuestID -eq "windows9_64Guest" ` + -or $_.GuestID -eq "windows2019srv_64Guest" ` + -or $_.GuestID -eq "windows2019srvNext_64Guest") } +$vmviewwin = $vmwin | Get-View + +$Outputwin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewwin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputWin += $IP + "`n" + } + } + } +} + +#If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline} +If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline } + + + +##Linux + +#Output File +$OutFileLin = "c:\inetpub\wwwroot\Lin.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileLin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Lin\$Timestamp-Lin.txt" +Remove-Item $OutFileLin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "centos6_64Guest" ` + -or $_.GuestID -eq "centos64Guest" ` + -or $_.GuestID -eq "centos7_64Guest" ` + -or $_.GuestID -eq "oracleLinux64Guest" ` + -or $_.GuestID -eq "oracleLinux7_64Guest" ` + -or $_.GuestID -eq "rhel4Guest" ` + -or $_.GuestID -eq "rhel5Guest" ` + -or $_.GuestID -eq "rhel5_64Guest" ` + -or $_.GuestID -eq "rhel6Guest" ` + -or $_.GuestID -eq "rhel6_64Guest" ` + -or $_.GuestID -eq "rhel7_64Guest" ` + -or $_.GuestID -eq "rhel8_64Guest" ` + -or $_.GuestID -eq "rhel9_64Guest" ` + -or $_.GuestID -eq "sles11_64Guest" ` + -or $_.GuestID -eq "sles12_64Guest" ` + -or $_.GuestID -eq "ubuntu64Guest") } +$vmviewlin = $vmLin | Get-View + +$OutputLin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewlin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputLin += $IP + "`n" + } + } + } +} + +#If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline} +If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline } + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDOneViewServerInventoryToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDOneViewServerInventoryToSql.ps1 new file mode 100644 index 0000000..83a0fcb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDOneViewServerInventoryToSql.ps1 @@ -0,0 +1,270 @@ +<# +.SYNOPSIS + Daily HPE OneView enclosure and server inventory for PowerBI trending and lifecycle planning. + +.DESCRIPTION + Iterates across all configured HPE OneView appliances, collecting enclosure and server + hardware metadata including compute capacity, power state, and server profile assignment. + Exports timestamped CSVs and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis and + physical hardware purchasing / lifecycle decisions. + + Appliances processed: + itdoneviewp1.nd.gov - Rack servers only (no enclosures) + itdbissyncompp1.nd.gov - Synergy enclosures + servers + itdmdnsyncompp1.nd.gov - Synergy enclosures + servers + +.NOTES + Run the following DDL once to create the destination tables: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Enclosure] + + CREATE TABLE [dbo].[VMware_Trends_Enclosure] ( + [ReportDate] DATETIME2 NOT NULL, + [ApplianceConnection] NVARCHAR(100) NULL, + [EnclosureName] NVARCHAR(255) NOT NULL, + [EnclosureModel] NVARCHAR(255) NULL, + [EnclosureSerialNumber] NVARCHAR(100) NULL, + [Status] NVARCHAR(50) NULL, + [DeviceBayCount] INT NULL + ) + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Server] + + CREATE TABLE [dbo].[VMware_Trends_Server] ( + [ReportDate] DATETIME2 NOT NULL, + [ApplianceConnection] NVARCHAR(100) NULL, + [EnclosureName] NVARCHAR(255) NULL, + [BayNumber] INT NULL, + [ServerHardwareName] NVARCHAR(255) NOT NULL, + [ServerName] NVARCHAR(255) NULL, + [ServerModel] NVARCHAR(255) NULL, + [ServerSerialNumber] NVARCHAR(100) NULL, + [Status] NVARCHAR(50) NULL, + [PowerState] NVARCHAR(50) NULL, + [ServerProfileName] NVARCHAR(255) NULL, + [ProcessorType] NVARCHAR(255) NULL, + [ProcessorCount] INT NULL, + [MemoryGB] DECIMAL(10,2) NULL, + [FormFactor] NVARCHAR(100) NULL + ) + + EnclosureName and BayNumber are NULL for rack-mounted servers not seated in an enclosure. + ServerName is the iLO/DNS hostname populated once a server profile is assigned. +#> +[CmdletBinding()] +param( +) + +#region --- Setup --------------------------------------------------------------- +[string[]] $OVHostnames = @( + 'itdoneviewp1.nd.gov', + 'itdbissyncompp1.nd.gov', + 'itdmdnsyncompp1.nd.gov' +) +[string] $OutputPath = 'C:\temp\OV_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $EnclosureTable = 'VMware_Trends_Enclosure' +[string] $ServerTable = 'VMware_Trends_Server' +[System.Management.Automation.PSCredential] $OVCredential = $Secret:ndgov_svcitdvmhpe +[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "OVServerInventory_$DateStamp.log") -Append + +#endregion + +#region --- Collect Data From All Appliances ----------------------------------- + +$AllEnclosureResults = [System.Collections.Generic.List[PSCustomObject]]::new() +$AllServerResults = [System.Collections.Generic.List[PSCustomObject]]::new() + +foreach ($OVHostname in $OVHostnames) { + + Write-Verbose "Connecting to HPE OneView: $OVHostname" + Connect-OVMgmt -Hostname $OVHostname -Credential $OVCredential -AuthLoginDomain nd.gov -LoginAcknowledge + + #--- Enclosures ------------------------------------------------------------ + + Write-Verbose "[$OVHostname] Gathering enclosures..." + $Enclosures = Get-OVEnclosure + + # Build URI map for server lookups (only populated if there are enclosures) + $EnclosureUriMap = @{} + foreach ($Enclosure in $Enclosures) { + $EnclosureUriMap[$Enclosure.uri] = $Enclosure.name + + $AllEnclosureResults.Add([PSCustomObject]@{ + ReportDate = $Timestamp + ApplianceConnection = $OVHostname + EnclosureName = $Enclosure.name + EnclosureModel = $Enclosure.model + EnclosureSerialNumber = $Enclosure.serialNumber + Status = $Enclosure.status + DeviceBayCount = ($Enclosure.deviceBays | Measure-Object).Count + }) + } + + #--- Servers --------------------------------------------------------------- + + Write-Verbose "[$OVHostname] Gathering servers..." + $Servers = Get-OVServer | Where-Object { $_.serverName -like 'itdvm*' } + + # Build profile URI map for this appliance + $ProfileUriMap = @{} + Get-OVServerProfile | ForEach-Object { + $ProfileUriMap[$_.uri] = $_.name + } + + Write-Verbose "[$OVHostname] Processing $($Servers.Count) servers..." + + foreach ($Server in $Servers) { + + $EnclosureName = if ($Server.locationUri) { + $EnclosureUriMap[$Server.locationUri] + } else { + $null + } + + $ProfileName = if ($Server.serverProfileUri) { + $ProfileUriMap[$Server.serverProfileUri] + } else { + $null + } + + $MemoryGB = if ($null -ne $Server.memoryMb -and $Server.memoryMb -gt 0) { + [Math]::Round($Server.memoryMb / 1024, 2) + } else { + $null + } + + $AllServerResults.Add([PSCustomObject]@{ + ReportDate = $Timestamp + ApplianceConnection = $OVHostname + EnclosureName = $EnclosureName + BayNumber = if ($null -ne $Server.position) { [int]$Server.position } else { $null } + ServerHardwareName = $Server.name + ServerName = $Server.serverName + ServerModel = $Server.model + ServerSerialNumber = $Server.serialNumber + Status = $Server.status + PowerState = $Server.powerState + ServerProfileName = $ProfileName + ProcessorType = $Server.processorType + ProcessorCount = if ($null -ne $Server.processorCount) { [int]$Server.processorCount } else { $null } + MemoryGB = $MemoryGB + FormFactor = $Server.formFactor + }) + } + + Disconnect-OVMgmt + Write-Verbose "[$OVHostname] Disconnected." +} + +#endregion + +#region --- Export CSVs -------------------------------------------------------- + +$EnclosureCsv = Join-Path $OutputPath "OVEnclosures_$DateStamp.csv" +$ServerCsv = Join-Path $OutputPath "OVServers_$DateStamp.csv" + +$AllEnclosureResults | Export-Csv -Path $EnclosureCsv -NoTypeInformation +$AllServerResults | Export-Csv -Path $ServerCsv -NoTypeInformation + +Write-Verbose "Exported $($AllEnclosureResults.Count) enclosure records to: $EnclosureCsv" +Write-Verbose "Exported $($AllServerResults.Count) server records to: $ServerCsv" + +#endregion + +#region --- SQL Insert: Enclosures --------------------------------------------- + +$EnclosureTable_DT = [System.Data.DataTable]::new() + +$EnclosureColDefs = [ordered]@{ + ReportDate = [datetime] + ApplianceConnection = [string] + EnclosureName = [string] + EnclosureModel = [string] + EnclosureSerialNumber = [string] + Status = [string] + DeviceBayCount = [int] +} + +foreach ($Col in $EnclosureColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$EnclosureTable_DT.Columns.Add($Column) +} + +foreach ($Row in $AllEnclosureResults) { + $DataRow = $EnclosureTable_DT.NewRow() + foreach ($Col in $EnclosureColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$EnclosureTable_DT.Rows.Add($DataRow) +} + +Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' ` + -TableName $EnclosureTable -Credential $SqlCredential -InputData $EnclosureTable_DT + +Write-Verbose "Inserted $($EnclosureTable_DT.Rows.Count) enclosure records into [$Database].[dbo].[$EnclosureTable]" + +#endregion + +#region --- SQL Insert: Servers ------------------------------------------------ + +$ServerTable_DT = [System.Data.DataTable]::new() + +$ServerColDefs = [ordered]@{ + ReportDate = [datetime] + ApplianceConnection = [string] + EnclosureName = [string] + BayNumber = [int] + ServerHardwareName = [string] + ServerName = [string] + ServerModel = [string] + ServerSerialNumber = [string] + Status = [string] + PowerState = [string] + ServerProfileName = [string] + ProcessorType = [string] + ProcessorCount = [int] + MemoryGB = [decimal] + FormFactor = [string] +} + +foreach ($Col in $ServerColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$ServerTable_DT.Columns.Add($Column) +} + +foreach ($Row in $AllServerResults) { + $DataRow = $ServerTable_DT.NewRow() + foreach ($Col in $ServerColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$ServerTable_DT.Rows.Add($DataRow) +} + +Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' ` + -TableName $ServerTable -Credential $SqlCredential -InputData $ServerTable_DT + +Write-Verbose "Inserted $($ServerTable_DT.Rows.Count) server records into [$Database].[dbo].[$ServerTable]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------ +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareClusterMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareClusterMetadataToSql.ps1 new file mode 100644 index 0000000..c923021 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareClusterMetadataToSql.ps1 @@ -0,0 +1,192 @@ +<# +.SYNOPSIS + Daily VMware Cluster metadata report for PowerBI trending and capacity planning. + +.DESCRIPTION + Collects cluster-level metadata from vCenter including DRS/HA configuration, + aggregate compute capacity, and effective resource availability. + Exports a timestamped CSV and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis. + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Cluster] + + CREATE TABLE [dbo].[VMware_Trends_Cluster] ( + [ReportDate] DATETIME2 NOT NULL, + [ClusterName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [DrsEnabled] BIT NOT NULL, + [DrsMode] NVARCHAR(50) NULL, + [HaEnabled] BIT NOT NULL, + [HostCount] INT NULL, + [EffectiveHostCount] INT NULL, + [TotalCpuCores] INT NULL, + [TotalCpuMhz] INT NULL, + [EffectiveCpuMhz] INT NULL, + [TotalMemoryGB] DECIMAL(10,2) NULL, + [EffectiveMemoryGB] DECIMAL(10,2) NULL, + [UsedMemoryGB] DECIMAL(10,2) NULL, + [VMCount] INT NULL + ) + + TotalCpuMhz, EffectiveCpuMhz, TotalMemoryGB, and EffectiveMemoryGB come from + vCenter's cluster summary (real-time aggregate). + UsedMemoryGB is summed from each host's current MemoryUsageGB. + TotalCpuCores is summed from each host's hardware CpuInfo. +#> +[CmdletBinding()] +param( +) + +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_Cluster' +[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "ClusterMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build Cluster -> Datacenter Lookup --------------------------------- + +Write-Verbose 'Building cluster-to-datacenter map...' +$ClusterDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-Cluster -Location $_ | ForEach-Object { + $ClusterDatacenterMap[$_.Name] = $DatacenterName + } +} + +#endregion + +#region --- Collect Cluster Data ----------------------------------------------- + +Write-Verbose 'Gathering clusters...' +$AllClusters = Get-Cluster + +Write-Verbose "Processing $($AllClusters.Count) clusters..." + +$Results = foreach ($Cluster in $AllClusters) { + + $Summary = $Cluster.ExtensionData.Summary # reuse for all summary fields + + #--- Aggregate host-level stats that vCenter summary does not expose + $ClusterHosts = Get-VMHost -Location $Cluster + $TotalCpuCores = ($ClusterHosts | ForEach-Object { + $_.ExtensionData.Hardware.CpuInfo.NumCpuCores + } | Measure-Object -Sum).Sum + $UsedMemoryGB = [Math]::Round( + ($ClusterHosts | Measure-Object -Property MemoryUsageGB -Sum).Sum, 2 + ) + $VMCount = ($ClusterHosts | ForEach-Object { + ($_.ExtensionData.Vm | Measure-Object).Count + } | Measure-Object -Sum).Sum + + #--- Capacity from cluster summary + $TotalCpuMhz = $Summary.TotalCpu # MHz + $EffectiveCpuMhz = $Summary.EffectiveCpu # MHz + $TotalMemoryGB = [Math]::Round($Summary.TotalMemory / 1GB, 2) # bytes -> GB + $EffectiveMemGB = [Math]::Round($Summary.EffectiveMemory / 1KB, 2) # MB -> GB + + [PSCustomObject]@{ + ReportDate = $Timestamp + ClusterName = $Cluster.Name + Datacenter = $ClusterDatacenterMap[$Cluster.Name] + DrsEnabled = $Cluster.DrsEnabled + DrsMode = $Cluster.DrsAutomationLevel + HaEnabled = $Cluster.HAEnabled + HostCount = $Summary.NumHosts + EffectiveHostCount = $Summary.NumEffectiveHosts + TotalCpuCores = [int]$TotalCpuCores + TotalCpuMhz = $TotalCpuMhz + EffectiveCpuMhz = $EffectiveCpuMhz + TotalMemoryGB = $TotalMemoryGB + EffectiveMemoryGB = $EffectiveMemGB + UsedMemoryGB = $UsedMemoryGB + VMCount = [int]$VMCount + } +} + +#endregion + +#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "ClusterMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) cluster records to: $OutputFile" + +#endregion + +#region --- SQL Insert --------------------------------------------------------- + +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + ClusterName = [string] + Datacenter = [string] + DrsEnabled = [bool] + DrsMode = [string] + HaEnabled = [bool] + HostCount = [int] + EffectiveHostCount = [int] + TotalCpuCores = [int] + TotalCpuMhz = [int] + EffectiveCpuMhz = [int] + TotalMemoryGB = [decimal] + EffectiveMemoryGB = [decimal] + UsedMemoryGB = [decimal] + VMCount = [int] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) cluster records into [$Database].[dbo].[$Table]" + +#endregion + +Disconnect-ITDvCenter + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareHostMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareHostMetadataToSql.ps1 new file mode 100644 index 0000000..686c80a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareHostMetadataToSql.ps1 @@ -0,0 +1,216 @@ +<# +.SYNOPSIS + Daily VMware Host metadata report for PowerBI trending and hardware capacity planning. + +.DESCRIPTION + Collects ESXi host metadata from vCenter including hardware, compute capacity, and + version information. Exports a timestamped CSV and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis and + physical hardware purchasing / lifecycle decisions. + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Host] + + CREATE TABLE [dbo].[VMware_Trends_Host] ( + [ReportDate] DATETIME2 NOT NULL, + [HostName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [Cluster] NVARCHAR(100) NULL, + [ConnectionState] NVARCHAR(50) NULL, + [PowerState] NVARCHAR(50) NULL, + [InMaintenanceMode] BIT NOT NULL, + [Model] NVARCHAR(255) NULL, + [ProcessorType] NVARCHAR(255) NULL, + [CpuSockets] INT NULL, + [CoresPerSocket] INT NULL, + [TotalCpuCores] INT NULL, + [CpuMhz] INT NULL, + [TotalCpuMhz] INT NULL, + [MemoryTotalGB] DECIMAL(10,2) NULL, + [MemoryUsageGB] DECIMAL(10,2) NULL, + [VMCount] INT NULL, + [EsxiVersion] NVARCHAR(50) NULL, + [EsxiBuild] NVARCHAR(50) NULL, + [UptimeDays] DECIMAL(10,2) NULL + ) + + MemoryUsageGB reflects real-time memory consumed by running VMs at the time of collection. + UptimeDays will be NULL for hosts that are powered off or disconnected. +#> +[CmdletBinding()] +param( +) + +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_Host' +[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "VMHostMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-host queries) - + +Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...' +$HostClusterMap = @{} +$HostDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostDatacenterMap[$_.Name] = $DatacenterName + } +} + +Get-Cluster | ForEach-Object { + $ClusterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostClusterMap[$_.Name] = $ClusterName + } +} + +#endregion + +#region --- Collect Host Data -------------------------------------------------- + +Write-Verbose 'Gathering hosts...' +$AllHosts = $HostDatacenterMap.Keys | ForEach-Object { Get-VMHost -Name $_ } + +Write-Verbose "Processing $($AllHosts.Count) hosts..." + +$Results = foreach ($VMHost in $AllHosts) { + + $Ext = $VMHost.ExtensionData # single API object -- reuse for all fields + + #--- CPU info from hardware summary + $CpuSockets = $Ext.Hardware.CpuInfo.NumCpuPackages + $TotalCpuCores = $Ext.Hardware.CpuInfo.NumCpuCores + $CoresPerSocket = if ($CpuSockets -gt 0) { [int]($TotalCpuCores / $CpuSockets) } else { $null } + $CpuMhz = $Ext.Hardware.CpuInfo.Hz / 1000000 # Hz -> MHz + $TotalCpuMhz = $Ext.Summary.Hardware.CpuMhz * $TotalCpuCores + + #--- Memory + $MemoryTotalGB = [Math]::Round($VMHost.MemoryTotalGB, 2) + $MemoryUsageGB = [Math]::Round($VMHost.MemoryUsageGB, 2) + + #--- VM count on this host right now + $VMCount = ($Ext.Vm | Measure-Object).Count + + #--- Uptime (null when host is powered off / disconnected) + $UptimeDays = $null + $BootTime = $Ext.Runtime.BootTime + if ($null -ne $BootTime) { + $UptimeDays = [Math]::Round(($RunDate - $BootTime).TotalDays, 2) + } + + [PSCustomObject]@{ + ReportDate = $Timestamp + HostName = $VMHost.Name + Datacenter = $HostDatacenterMap[$VMHost.Name] + Cluster = $HostClusterMap[$VMHost.Name] + ConnectionState = $VMHost.ConnectionState + PowerState = $VMHost.PowerState + InMaintenanceMode = $VMHost.ExtensionData.Runtime.InMaintenanceMode + Model = $Ext.Hardware.SystemInfo.Model + ProcessorType = $VMHost.ProcessorType + CpuSockets = $CpuSockets + CoresPerSocket = $CoresPerSocket + TotalCpuCores = $TotalCpuCores + CpuMhz = [int]$CpuMhz + TotalCpuMhz = $TotalCpuMhz + MemoryTotalGB = $MemoryTotalGB + MemoryUsageGB = $MemoryUsageGB + VMCount = $VMCount + EsxiVersion = $VMHost.Version + EsxiBuild = $VMHost.Build + UptimeDays = $UptimeDays + } +} + +#endregion + +#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "VMHostMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) host records to: $OutputFile" + +#endregion + +#region --- SQL Insert --------------------------------------------------------- + +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + HostName = [string] + Datacenter = [string] + Cluster = [string] + ConnectionState = [string] + PowerState = [string] + InMaintenanceMode = [bool] + Model = [string] + ProcessorType = [string] + CpuSockets = [int] + CoresPerSocket = [int] + TotalCpuCores = [int] + CpuMhz = [int] + TotalCpuMhz = [int] + MemoryTotalGB = [decimal] + MemoryUsageGB = [decimal] + VMCount = [int] + EsxiVersion = [string] + EsxiBuild = [string] + UptimeDays = [decimal] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) host records into [$Database].[dbo].[$Table]" + +Disconnect-ITDvCenter + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareVMMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareVMMetadataToSql.ps1 new file mode 100644 index 0000000..8c9ba7c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Sync-ITDVMwareVMMetadataToSql.ps1 @@ -0,0 +1,300 @@ +<# +.SYNOPSIS + Daily VM metadata report for PowerBI trending and hardware capacity planning. + +.DESCRIPTION + Collects VM metadata from vCenter including compute, storage, OS, and VMware Tools + information using only data available within vCenter (no direct guest connections). + Exports a timestamped CSV each run -- append daily runs to build a historical dataset + suitable for PowerBI trend analysis and physical hardware purchasing decisions. + +.PARAMETER vCenterServers + One or more vCenter server hostnames. Defaults to itdvmvc1.nd.gov and itdvmvc2.nd.gov. + +.PARAMETER DatacenterFilter + Wildcard filter applied to datacenter names. Defaults to 'Primary*'. + +.PARAMETER OutputPath + Directory where CSV and log files are written. + Defaults to C:\ITDSCRIPT\Reports\VMMetadata. + +.PARAMETER CredentialPath + Path to a saved PSCredential XML file for unattended/scheduled runs. + Create one interactively with: + Get-Credential | Export-Clixml -Path C:\ITDSCRIPT\Creds\vCenter.xml + When omitted the script prompts for credentials. + +.EXAMPLE + # Interactive run + .\VMware-VMDailyMetadataReport.ps1 + +.EXAMPLE + # Scheduled / unattended run + .\VMware-VMDailyMetadataReport.ps1 -CredentialPath 'C:\ITDSCRIPT\Creds\vCenter.xml' + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_VM] + + CREATE TABLE [dbo].[VMware_Trends_VM] ( + [ReportDate] DATETIME2 NOT NULL, + [VMName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [Cluster] NVARCHAR(100) NULL, + [PowerState] NVARCHAR(50) NULL, + [IsSRMPlaceholder] BIT NOT NULL, + [StoragePlatform] NVARCHAR(100) NULL, + [GuestOS] NVARCHAR(255) NULL, + [vCPUs] INT NULL, + [MemoryGB] DECIMAL(10,2) NULL, + [ProvisionedSpaceGB] DECIMAL(12,2) NULL, + [UsedSpaceGB] DECIMAL(12,2) NULL, + [GuestDiskCapacityGB] DECIMAL(12,2) NULL, + [GuestDiskUsedGB] DECIMAL(12,2) NULL, + [ToolsRunningStatus] NVARCHAR(100) NULL, + [ToolsVersionStatus] NVARCHAR(100) NULL, + [ToolsVersion] NVARCHAR(50) NULL, + [Tag_DRProtection] NVARCHAR(100) NULL, + [Tag_AppName] NVARCHAR(255) NULL, + [Tag_VRDatastores] NVARCHAR(255) NULL, + [Tag_VRRPO] NVARCHAR(100) NULL, + [Tag_DTAP] NVARCHAR(50) NULL, + [Tag_StartupPriority] NVARCHAR(100) NULL, + [Tag_SRMRecoveryType] NVARCHAR(100) NULL, + [Tag_LicensingRestrictions] NVARCHAR(255) NULL + ) + + Guest OS disk capacity / used columns are NULL for powered-off VMs and SRM placeholders. +#> +[CmdletBinding()] +param( +) + +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_VM' +[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "VMMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-VM API calls) - + +Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...' +$HostClusterMap = @{} +$HostDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostDatacenterMap[$_.Name] = $DatacenterName + } +} + +Get-Cluster | ForEach-Object { + $ClusterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostClusterMap[$_.Name] = $ClusterName + } +} + +#endregion + +#region --- Collect VM Data ----------------------------------------------------- + +Write-Verbose "Gathering VMs" + +# Include ALL VMs (SRM placeholders flagged via column, not excluded). +# vCLS agent VMs are excluded -- they are vSphere internal and not customer workloads. +$AllVMs = Get-VM | Where-Object { $_.Name -notlike 'vCLS*' } + +#--- Pre-fetch all tag assignments in one API call (avoids per-VM Get-TagAssignment) +Write-Verbose 'Pre-fetching VM tag assignments...' +$TagLookup = @{} +Get-TagAssignment -Entity $AllVMs | ForEach-Object { + $VMId = $_.Entity.Id + $Cat = $_.Tag.Category.Name + $TagName = $_.Tag.Name + if (-not $TagLookup.ContainsKey($VMId)) { $TagLookup[$VMId] = @{} } + if ($TagLookup[$VMId].ContainsKey($Cat)) { + $TagLookup[$VMId][$Cat] += "; $TagName" + } else { + $TagLookup[$VMId][$Cat] = $TagName + } +} + +Write-Verbose "Processing $($AllVMs.Count) VMs..." + +$Results = foreach ($VM in $AllVMs) { + + $Ext = $VM.ExtensionData # single API object -- reuse for all fields + + #--- SRM placeholder detection + $IsSRMPlaceholder = $Ext.Summary.Config.ManagedBy.Type -eq 'placeholderVm' + + #--- Cluster / Datacenter (null-safe: standalone hosts have no cluster entry) + $ClusterName = $HostClusterMap[$VM.VMHost.Name] + $DatacenterName = $HostDatacenterMap[$VM.VMHost.Name] + + #--- Tag assignments (pre-fetched; null when category not assigned to this VM) + $VMTags = if ($TagLookup.ContainsKey($VM.Id)) { $TagLookup[$VM.Id] } else { @{} } + + #--- Storage platform parsed from datastore name convention: VMCLUSTER_LUN_PLATFORM_Desc + # Segment 2 = storage platform identifier (e.g. FS92, A9K). + # Cluster grouping uses the compute Cluster column -- no need to re-derive it here. + $StoragePlatforms = foreach ($DSName in $Ext.Config.DatastoreUrl.Name) { + $Segments = $DSName -split '_' + if ($Segments.Count -ge 3) { $Segments[2] } + } + $StoragePlatform = ($StoragePlatforms | Sort-Object -Unique) -join '; ' + + #--- VMware Tools guest disk info + # Populated only when Tools is running; null otherwise. + $GuestDiskCapacityGB = $null + $GuestDiskUsedGB = $null + if ($Ext.Guest.Disk) { + $TotalCapBytes = ($Ext.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum + $TotalFreeBytes = ($Ext.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum + $GuestDiskCapacityGB = [Math]::Round($TotalCapBytes / 1GB, 2) + $GuestDiskUsedGB = [Math]::Round(($TotalCapBytes - $TotalFreeBytes) / 1GB, 2) + } + + [PSCustomObject]@{ + # --- Identity & grouping + ReportDate = $Timestamp # for PowerBI time-series/trend axis + VMName = $VM.Name + Datacenter = $DatacenterName + Cluster = $ClusterName + PowerState = $VM.PowerState + IsSRMPlaceholder = $IsSRMPlaceholder + StoragePlatform = $StoragePlatform + GuestOS = $Ext.Guest.GuestFullName + + # --- Compute + vCPUs = $VM.NumCpu + MemoryGB = $VM.MemoryGB + + # --- Datastore-level storage + # ProvisionedSpaceGB : maximum the VM could consume (thin disks counted at max size) + # UsedSpaceGB : bytes actually committed on datastores right now + ProvisionedSpaceGB = [Math]::Round($VM.ProvisionedSpaceGB, 2) + UsedSpaceGB = [Math]::Round($VM.UsedSpaceGB, 2) + + # --- Guest OS-level storage (from VMware Tools; null when Tools not running) + # GuestDiskCapacityGB : sum of all volume capacities seen inside the guest + # GuestDiskUsedGB : sum of space consumed across those volumes + GuestDiskCapacityGB = $GuestDiskCapacityGB + GuestDiskUsedGB = $GuestDiskUsedGB + + # --- VMware Tools + # ToolsRunningStatus : guestToolsRunning | guestToolsNotRunning | guestToolsExecutingScripts + # ToolsVersionStatus : guestToolsCurrent | guestToolsNeedUpgrade | guestToolsUnmanaged | guestToolsTooNew + # ToolsVersion : numeric build version string reported by vCenter + ToolsRunningStatus = $Ext.Guest.ToolsRunningStatus + ToolsVersionStatus = $Ext.Guest.ToolsVersionStatus + ToolsVersion = $Ext.Guest.ToolsVersion + + # --- vCenter Tags + Tag_DRProtection = $VMTags['DR Protection'] + Tag_AppName = $VMTags['AppName'] + Tag_VRDatastores = $VMTags['VR Datastores'] + Tag_VRRPO = $VMTags['VR RPO'] + Tag_DTAP = $VMTags['DTAP'] + Tag_StartupPriority = $VMTags['StartupPriority'] + Tag_SRMRecoveryType = $VMTags['SRM Recovery Type'] + Tag_LicensingRestrictions = $VMTags['LicensingRestrictions'] + } +} + +#endregion + +<#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "VMMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) VM records to: $OutputFile" + +#endregion +#> +#region --- SQL Insert --------------------------------------------------------- + +# Build a typed DataTable so Write-SqlTableData knows each column's type +# even when nullable columns contain null values. Type inference from raw +# PSCustomObjects fails when the first row has a null in a numeric column. +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + VMName = [string] + Datacenter = [string] + Cluster = [string] + PowerState = [string] + IsSRMPlaceholder = [bool] + StoragePlatform = [string] + GuestOS = [string] + vCPUs = [int] + MemoryGB = [decimal] + ProvisionedSpaceGB = [decimal] + UsedSpaceGB = [decimal] + GuestDiskCapacityGB = [decimal] + GuestDiskUsedGB = [decimal] + ToolsRunningStatus = [string] + ToolsVersionStatus = [string] + ToolsVersion = [string] + Tag_DRProtection = [string] + Tag_AppName = [string] + Tag_VRDatastores = [string] + Tag_VRRPO = [string] + Tag_DTAP = [string] + Tag_StartupPriority = [string] + Tag_SRMRecoveryType = [string] + Tag_LicensingRestrictions = [string] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) VM records into [$Database].[dbo].[$Table]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Update-ITDVMwareILOSslCertificate.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Update-ITDVMwareILOSslCertificate.ps1 new file mode 100644 index 0000000..d505104 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Administration/Update-ITDVMwareILOSslCertificate.ps1 @@ -0,0 +1,247 @@ +<# NOT FUNCTIONAL YET - WORK IN PROGRESS +.SYNOPSIS + Update/renew any expired iLO certificates in the VMware/Synergy environment +.DESCRIPTION + Update/renew any expired iLO certificates in the VMware/Synergy environment +.NOTES + # retrieve all iLO from Synergy + # find all certificates expiring in the next 3 days, or ones that do not have nd.gov in name, add to an array + # loop through list + ## connect to ilo + ## generate CSR + ## send CSR to sectigo to generate new + ## wait for approval + ## download new cert + ## upload/update/set on iLO +.LINK + +.EXAMPLE + Test-MyTestFunction -Verbose + Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines +#> + +[CmdletBinding()] +param ( + [Parameter(ParameterSetName = 'ByHostName')] + [string[]] + $HostName = $null, + + [Parameter(ParameterSetName = 'SynergyDiscovery')] + [switch] + $SynergyDiscovery + +) + +function Get-SectigoToken { + Write-Verbose -Message "Retrieving Sectigo API key for VMware" -Verbose + $SectigoCred = Get-ITDPassword -Title "Sectigo API key for VMware" -UserName "f595aa76-c26b-4664-b95d-cb805cc7ff4e" + Write-Verbose -Message "Confirming SectigoCred is $($SectigoCred.UserName)" -Verbose + $AuthBody = @{ + grant_type = 'client_credentials' + #client_id = $Secret:sectigo_vmware.UserName + #client_secret = $Secret:sectigo_vmware.GetNetworkCredential().Password + client_id = $SectigoCred.UserName + client_secret = $SectigoCred.GetNetworkCredential().Password + } + + $AuthBaseAPIUrl = 'https://auth.sso.sectigo.com' + + $tokenEndpoint = $AuthBaseAPIUrl + '/auth/realms/apiclients/protocol/openid-connect/token' + $env:SectigoToken = (Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType 'application/x-www-form-urlencoded' -Body $AuthBody).access_token + + Return $env:SectigoToken +} + +Write-Verbose -Message "Retrieving OneView Service Account credentials" -Verbose +$OVCred = Get-ITDPassword -Title "VMware iLO Service Account" -UserName "ndgov\svcitdvmhpe" +Write-Verbose -Message "Confirming OneView is $($OVCred.UserName)" -Verbose + +Import-Module HPEiLOCmdlets -Force + +Write-Verbose -Message "Gather PSUniversal Job Information" -Verbose +$PSUJobId = $UAJob.Id + +Write-Verbose -Message "Set static variables" -Verbose +$RequesterEmail = 'vmware@nd.gov' +$AppName = "Infra-VMware" +$ServerTypeCode = "Linux" +$Format = "x509CO" +$OrgId = 8133 # Sectigo OrgDept ID for State of North Dakota Information Technology Department - Cloud & Infrastructure +$CertType = 2375 # Sectigo Cert Type for Standard SSL Multi-Domain + +$BaseAPIUrl = 'https://admin.hard.sectigo.com' + +switch ($PSCmdlet.ParameterSetName) { + 'ByHostName' { + $AllILOServers = $HostName + } + 'SynergyDiscovery' { + Write-Verbose -Message "Retrieving iLO information from OneView/Synergy" -Verbose + $OneviewServers = @('itdmdnsyncompt1.nd.gov', 'itdmdnsyncompp1.nd.gov', 'itdbissyncompp1.nd.gov') + $AllILOServers = @() + ForEach ($OneviewServer in $OneViewServers ) { + Write-Verbose -Message "Connecting to OneView server $OneviewServer" -Verbose + Connect-OVMgmt -Hostname $OneviewServer -Credential $OVCred -AuthLoginDomain nd.gov -LoginAcknowledge + $AllILOServers += (Get-OVServer).ServerName | ForEach-Object { + $_.split('.')[0] + "lo.nd.gov" + } + Disconnect-OVMgmt + } + } + default { + Write-Error -Message "Invalid parameter set." + exit 1 + } +} + +Write-Verbose -Message "Checking iLO certificates for expiration or invalid issuer/commonname" -Verbose +$AlliLOToRenew = @() +ForEach ($iLODnsName in $AllILOServers) { + Write-Verbose -Message "Checking certificate for iLO $iLODnsName" -Verbose + $cert = Get-SslCertificate -DNSName $iLODnsName + + If ( $cert.NotAfter.AddDays(-7) -le (Get-Date) ) { + Write-Warning -Message "Certificate for $iLODnsName expires on $($cert.NotAfter), add to renewal list." + $AlliLOToRenew += $iLODnsName + } + + If ( $cert.subject -notlike "*.nd.gov*") { + Write-Warning -Message "Certificate for $iLODnsName is not a ND.gov cert, add to renewal list." + $AlliLOToRenew += $iLODnsName + } +} + +ForEach ($iLOToRenew in $AlliLOToRenew | Select-Object -Unique) { + Write-Verbose -Message "Processing iLO $iLOToRenew for certificate renewal" -Verbose + + $iLOCred = $null + switch ($iLOToRenew) { + { $_ -like "*bis*" } { + Write-Verbose -Message "BIS iLO detected, getting credentials for itdbissyncompp1" -Verbose + $iloCred = Get-ITDPassword -Title "itdbissyncompp1 iLO" -UserName "Administrator"; + } + { $_ -like "*mdn*" } { + Write-Verbose -Message "MDN iLO detected, getting credentials for itdmdnsyncompp1" -Verbose + $iloCred = Get-ITDPassword -Title "itdmdnsyncompp1 iLO" -UserName "Administrator"; + } + { $_ -like "*test*" } { + Write-Verbose -Message "TEST iLO detected, getting credentials for itdmdnsyncompt1" -Verbose + $iloCred = Get-ITDPassword -Title "itdmdnsyncompt1 iLO" -UserName "Administrator"; + } + default { Write-Error -Message "No iLO credentials found for $iLOToRenew, skipping."; continue; } + } + + try { + Write-Verbose -Message "Establishing connection to iLO $iLOToRenew" -Verbose + $iLOConnection = Connect-HPEiLO -Address $iLOToRenew -Credential $iLOCred -DisableCertificateAuthentication + Write-Verbose -Message "Generating CSR on iLO $iLOToRenew" -Verbose + Start-HPEiLOCertificateSigningRequest -Connection $iLOConnection ` + -CommonName $iLOConnection.Hostname ` + -Organization "State of North Dakota" ` + -Country US ` + -City Bismarck ` + -State "North Dakota" + + Start-Sleep -Seconds 30 ### for some reason if you check iLO for CSR too frequently it doesn't work + + Write-Verbose -Message "Getting CSR for $iLOToRenew" + $CsrData = $null + + While ($null -eq $CsrData.CertificateSigningRequest) { + try { + $CsrData = Get-HPEiLOCertificateSigningRequest -Connection $iLOConnection + } + catch { + Write-Warning -Message "CSR not ready yet for $iLOToRenew, waiting 10 seconds." + Start-Sleep -Seconds 10 + } + } + Disconnect-HPEiLO -Connection $iLOConnection + $iLOConnection = $null + + Write-Verbose -Message "Submitting CSR to Sectigo for $iLOToRenew" -Verbose + #Get-SectigoToken ## function above loaded into memory + + $EnrollBody = @{ + orgId = $OrgId; + certType = $CertType + term = 365; + comments = "iLO Certificate Renewal for $iLOToRenew" + serverType = $ServerTypeCode + csr = $CsrData.CertificateSigningRequest + externalRequester = "vmware@nd.gov" + customFields = @( + @{ + name = 'ApplicationName' + value = 'Infra-VMware' + } + ) + } + + $EnrollParams = @{ + Method = 'Post' + Uri = $BaseAPIUrl + "/api/ssl/v1/enroll" + Headers = @{ + "Authorization" = ("Bearer " + (Get-SectigoToken)) + "Content-Type" = "application/json" + } + Body = ($EnrollBody | ConvertTo-Json -Depth 10) + ContentType = 'application/json' + } + + $EnrollResponse = Invoke-RestMethod @EnrollParams + $OrderId = $EnrollResponse.sslId + + Write-Verbose -Message "Waiting for certificate issuance for $iLOToRenew" -Verbose + $Certificate = $null + + Start-Sleep -Seconds 15 + + While ($Certificate.status -ne "Issued") { + $ValidateUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}" + $ValidateSplat = @{ + Uri = $ValidateUrl + Method = 'Get' + Headers = @{ + "Authorization" = ("Bearer " + (Get-SectigoToken)) + "Content-Type" = "application/json" + } + } + + $Certificate = Invoke-RestMethod @ValidateSplat + If ($Certificate.status -ne "Issued") { + Write-Warning -Message "Certificate for $iLOToRenew not issued yet, waiting 15 seconds." + Start-Sleep -Seconds 15 + } + } + + Write-Verbose -Message "Downloading issued certificate for $iLOToRenew" -Verbose + $CollectUrl = $BaseAPIUrl + "/api/ssl/v1/collect/${OrderId}?format=${Format}" + + $CommonName = $Certificate.commonName + + $DownloadSplat = @{ + Uri = $CollectUrl + Method = 'Get' + Headers = @{ + "Authorization" = ("Bearer " + (Get-SectigoToken)) + "Content-Type" = "application/json" + } + UseBasicParsing = $true + } + + Write-Verbose -Message "Downloading certificate to F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem" -Verbose + Invoke-WebRequest @DownloadSplat -OutFile "F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem" + + Write-Verbose -Message "Importing new certificate to iLO $iLOToRenew" -Verbose + $CertificateToUpload = Get-Content -Path "F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem" -Raw + $iLOConnection = Connect-HPEiLO -Address $iLOToRenew -Credential $iLOCred -DisableCertificateAuthentication -Verbose + Import-HPEiLOCertificate -Certificate ($CertificateToUpload | Out-String) -Connection $iLOConnection -Force + Disconnect-HPEiLO -Connection $iLOConnection + + Write-Verbose -Message "Disconnecting from iLO $iLOToRenew" -Verbose + } + catch { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 new file mode 100644 index 0000000..1bc1377 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 @@ -0,0 +1,133 @@ +<##### +.SYNOPSIS + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.DESCRIPTION + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.NOTES + +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0017146 +#> + +[CmdletBinding()] +param ( + [Parameter( + Mandatory = $true, + HelpMessage = "The VMware virtual machine name. This is most commonly the FQDN. You can verify the virtual machine name by logging into vCenter. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back." + )] + [string[]] + $VMName = $null, + + [Parameter(Mandatory = $true, + HelpMessage = "The DateTime you want the snapshot to occur.")] + [datetime] + $DateTime = (Get-Date), + + [Parameter(Mandatory = $true, + HelpMessage = "How many hours the snapshot will exist. The snapshot will be automatically deleted after the duration. Maximum value is 72 hours.")] + [ValidateRange(1, 72)] + [int] + $DurationHours = 4, + + [Parameter(HelpMessage = "Email address that you want vCenter to notify when the snapshot is taken. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $Email = $null +) + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$StartDateTime = $DateTime +$EndDateTime = $StartDateTime.AddHours($DurationHours) +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +$StartDateTimeSql = $StartDateTime.ToString('yyyy/MM/dd HH:mm:ss') +$EndDateTimeSql = $EndDateTime.ToString('yyyy/MM/dd HH:mm:ss') + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr +Write-Verbose -Message "After Connect vCenter" -Verbose + + +ForEach ($name in $VMName) { + Write-Verbose -Message ("Add record to SQL") -Verbose + $SqlQuery = "INSERT INTO [$SnapshotTable] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('$Name', '$StartDateTimeSql', '$RequestedBy', $DurationHours, 'Requested', '$EndDateTimeSql','$Email','$PSUJobId');SELECT SCOPE_IDENTITY();" + Write-Verbose -Message $SqlQuery -Verbose + $SnapshotId = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose).Column1 + Write-Verbose -Message ("Snapshot ID is $SnapshotId") -Verbose + + Write-Verbose -Message "Get SQL record" -Verbose + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE ID='$SnapshotId'" + Write-Verbose -Message $SqlQuery -Verbose + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message $SqlRecord -Verbose + + Write-Verbose -Message ("Determine description metadata") -Verbose + $MetadataObj = @{ + Id = [int]$SnapshotId; + Taken = $StartDateTime; + Expire = $EndDateTime; + RequestedBy = $RequestedBy; + DurationHours = $DurationHours; + PSUJobIdRequest = $PSUJobId; + } + + Write-Verbose -Message ("Create VM Scheduled Task for Snapshot " + $SnapshotId) -Verbose + + $NewITDVMwareVMSnapshotTaskParams = @{ + VMName = $name; + Name = ("AutoSnap_" + $SnapshotId) + Description = $MetadataObj | ConvertTo-Json + DateTime = $StartDateTime; + } + + switch ($PSBoundParameters.Keys) { + Email { + $NewITDVMwareVMSnapshotTaskParams.Email = $Email + } + } + + try { + New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams -Verbose -ErrorAction Stop + Write-Verbose -Message ("Setting SQL status to Scheduled") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Scheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + + Write-Verbose -Message ($NewITDVMwareVMSnapshotTaskParams.Name + " has been scheduled.") -Verbose + } + catch { + Write-Verbose -Message "ObjectNotFound Error" -Verbose + switch ($Error[0].Exception.ErrorCategory) { + 'ObjectNotFound' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed, ObjectNotFound.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-VMNotFound' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + 'Default' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-GenericError' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Write-Error -Message $Error[0] + } +} + +Disconnect-ITDvCenter + +# Write-Verbose -Message ("If scheduled task is created successfully, create SNow CHG for this, using scheduled StartDateTime... work TBD") -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 new file mode 100644 index 0000000..fe4f523 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 @@ -0,0 +1,99 @@ +[CmdletBinding()] +param ( + [string] + $VMName, + + [int] + $Id, + + [switch] + $WhatIf +) + +$PSUJobId = $UAJob.Id + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose + +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +# find all VMs, with VMName if entered +If ($PSBoundParameters.ContainsKey('VMName')) { + Write-Verbose -Message "VMName parameter found $VMName" -Verbose + $VMs = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} +Else { + $VMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} + +# find expired snapshots of the VMs +If ($PSBoundParameters.ContainsKey('Id')) { + Write-Verbose -Message "ID parameter found $Id" -Verbose + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -EQ "AutoSnap_$Id" +} +Else { + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -Like "AutoSnap_2*" ##### Remove the '2' after SharePoint snapshots are all deleted +} + +ForEach ($Snapshot in $AllSnapshots) { + Write-Verbose -Message ("Start Snapshot " + $Snapshot.Description) -Verbose + $SnapshotObj = $null + + $SnapshotObj = $Snapshot.Description | ConvertFrom-Json + If ($null -ne $SnapshotObj -and $SnapshotObj.Expire -lt (Get-Date)) { + # remove snapshot if expired + If ($WhatIf) { + Write-Verbose -Message ("What if: Performing the operation Remove-Snapshot on Snapshot " + $Snapshot.Name) -Verbose + } + Else { + Write-Verbose -Message ("VMName: " + $Snapshot.VM.Name + " / Snapshot ID: " + $SnapshotObj.Id + " -- attempting removal") -Verbose + + # update SQL status to "Delete-Attempted" + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Delete-AutoAttempt', PSUJobIdDelete = '$PSUJobId' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + + # Remove Snapshot + $Snapshot | Remove-Snapshot -Confirm:$false -Verbose + + # confirm snapshot is truly gone, then update sql with results + If (Get-VM -Name $Snapshot.VM.Name | Get-Snapshot -Id $SnapshotObj.Id -ErrorAction SilentlyContinue) { + $RemoveStatus = $false + } + Else { + # snapshot does not exist + $RemoveStatus = $true + } + + # update SQL + switch ($RemoveStatus) { + $true { + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-AutoSuccess' WHERE ID = " + $Snapshot.Name.split('_')[1]) + } + $false { + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-AutoFailure' WHERE ID = " + $Snapshot.Name.split('_')[1]) + } + } + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + # do nothing + Write-Verbose -Message ("VMName: " + $Snapshot.VM.Name + " / Snapshot ID: " + $SnapshotObj.Id + " has not expired.") -Verbose + } +} + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 new file mode 100644 index 0000000..a54cded --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 @@ -0,0 +1,203 @@ +[CmdletBinding()] +param ( + [int] + $Id +) + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +# get list of All vCenter Scheduled Tasks +$si = Get-View ServiceInstance +$scheduledTaskManager = Get-View $Si.Content.ScheduledTaskManager +Write-Verbose -Message ("Gathering all scheduled tasks with AutoSnap in the task name, this will take some time") +$AllScheduledTasks = Get-View -Id $scheduledTaskManager.ScheduledTask | Where-Object { $_.Info.Name -like "AutoSnap*" } + +Write-Verbose -Message "Get SQL records with status of Scheduled" -Verbose +# get list of Scheduled from database +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Scheduled'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Scheduled status") -Verbose +Write-Verbose -Message "Start Scheduled > Taken Loops" +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + Write-Verbose -Message ("Setting SQL status to Taken") -Verbose + # if status has changed from requested to taken, update database status field + $TakenDateTimeSql = ($Snapshot.Description | ConvertFrom-Json).Taken.ToString('yyyy/MM/dd HH:mm:ss') + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Taken', TakenDateTime = '" + $TakenDateTimeSql + "' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + If ($SqlRecord.DateTime -lt (Get-Date)) { + Write-Error -Message ("AutoSnap_" + $SqlRecord.Id + " not found, and its requested datetime has passed") -Verbose + # Update SQL record to status Failed-ScheduledNotTaken + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-ScheduledNotTaken' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose +} + +Write-Verbose -Message "End Scheduled > Taken Loops" +$SqlRecord = $null +$SqlRecords = $null +$SqlQueryUpdate = $null + +# get list of taken from database +Write-Verbose -Message "Start Taken > Expire Loops" +Write-Verbose -Message "Get SQL records with status of Taken" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Taken'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Taken SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Taken status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + # if expired datetime is in the past, set status to expired + If ( ($Snapshot.Description | ConvertFrom-Json).Expire -lt (Get-Date)) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has expired.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Expired' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-Manual' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose + $SqlRecord = $null + $SqlRecords = $null + $SqlQueryUpdate = $null +} + +# get list of Expired from SQL database + +Write-Verbose -Message "Start Expired > Removed Loops" +Write-Verbose -Message "Get SQL records with status of Expired" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Expired'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Expired SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Expired status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + # if expired datetime is in the past, set status to expired + If ( ($Snapshot.Description | ConvertFrom-Json).Expire -lt (Get-Date)) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " is expired. Will be removed at next Removal run") -Verbose + #$SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Expired' WHERE ID = " + $Snapshot.Name.split('_')[1]) + #Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-Manual' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose + $SqlRecord = $null + $SqlRecords = $null + $SqlQueryUpdate = $null +} + + +# get list of requested from SQL database +Write-Verbose -Message "Start Requested > Scheduled Loops" +Write-Verbose -Message "Get SQL records with status of Requested" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Requested'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Requested SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Requested status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + # does the scheduled tasks exist? + If ($AllScheduledTasks | Where-Object { $_.Info.Name -eq ("AutoSnap_" + $SqlRecord.Id + '_' + $SqlRecord.VMName) }) { + # yes - update SQL status to Scheduled + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " vCenter scheduled task exists.") -Verbose + Write-Verbose -Message ("Setting SQL status to Scheduled") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Scheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + # no + # has date/time passed? (10 minute buffer) + If ($SqlRecord.DateTime -lt (Get-Date).AddMinutes(-10)) { + # yes - set SQL status to Failed-RequestedNotScheduled + Write-Warning -Message ("AutoSnap_" + $SqlRecord.Id + " was not scheduled before its datetime.") + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-RequestedNotScheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + # no ??? + } + Write-Error -Message ("AutoSnap_" + $SqlRecord.Id + " scheduled task does not exist.") + } +} +Write-Verbose -Message "End Requested > Scheduled Loops" +$SqlRecord = $null +$SqlRecords = $null +$SqlQueryUpdate = $null + +Disconnect-ITDvCenter diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 new file mode 100644 index 0000000..9713723 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 @@ -0,0 +1,90 @@ +Param( + [string] + $Ritm, + + [string] + $ComputerName +) +# $cat_item_sys_id = 'c64e27af47244610b7853238436d435d' +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Prep variable and SQL connection" -Verbose +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = "ServiceNow_RitmDump_ServerBuildRequestV1" + +$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm -IncludeCustomVariable -IncludeVariableSet + +ForEach ($Ritm in $AllRitms) { + Write-Verbose ("Start " + $Ritm.number) -Verbose + # get all variable set rows + $VariableSet = (Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -IncludeVariableSet).VariableSet + ForEach ($VSet in $VariableSet) { + Write-Verbose -Message ("Start " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # figure out values + $RitmNum = $Ritm.number.value + $RitmSysId = $Ritm.sys_id.value + $opened_at = $Ritm.opened_at.display_value + $requested_for = $Ritm.requested_for.display_value + $request_type = $Ritm.CustomVariable.request_type.value + $environment = $Ritm.CustomVariable.environment.value + $host_name_ref = $VSet.host_name_ref + $host_name = If ($VSet.host_name_ref) { + (Get-ITDServiceNowRecord -Table cmdb_ci -SysId $VSet.host_name_ref).Name.display_value + } + Else { + $VSet.host_name + } + $server_type = $VSet.server_type + $operating_system = $VSet.operating_system + $target_os_version_linux = $VSet.target_os_version_linux + $target_os_version_windows = $VSet.target_os_version_windows + $target_platform = $VSet.target_platform + $processors = $VSet.processors + $memory_gb = $VSet.memory_gb + $cidr_block_sys_id = $VSet.cidr_block + $cidr_block = (Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId $cidr_block_sys_id).subnet.display_value + $vlan_id = $VSet.vlan_id + $data_center = $VSet.data_center + $licensing_restrictions = $VSet.licensing_restrictions + $application_info_sys_id = $VSet.application_info + $application_info = (Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId $application_info_sys_id).name.display_value + $support_hours = $VSet.support_hours + $dr_protection = $VSet.dr_protection + $startup_priority = $VSet.startup_priority + $disk_1_os = $VSet.disk_1_os + $disk_2_swap_disk = $VSet.disk_2_swap_disk + $disk_3 = $VSet.disk_3 + $disk_4 = $VSet.disk_4 + $disk_5 = $VSet.disk_5 + $disk_6 = $VSet.disk_6 + $disk_7 = $VSet.disk_7 + $disk_8 = $VSet.disk_8 + $disk_9 = $VSet.disk_9 + $disk_10 = $VSet.disk_10 + $disk_11 = $VSet.disk_11 + $disk_12 = $VSet.disk_12 + $disk_13 = $VSet.disk_13 + $disk_14 = $VSet.disk_14 + $disk_15 = $VSet.disk_15 + $disk_16 = $VSet.disk_16 + $special_instructions = $Ritm.CustomVariable.special_instructions.value + $customer_request = $Ritm.CustomVariable.customer_request.value + $additional_comments = $Ritm.CustomVariable.additional_comments.value + + If ($host_name -eq $ComputerName) { + Write-Verbose -Message ("Add to SQL " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # add record to SQL + $SqlQuery = "INSERT INTO [$Table] ( + RitmNum, RitmSysId, opened_at,requested_for,request_type,environment,host_name_ref,host_name,server_type,operating_system,target_os_version_linux,target_os_version_windows,target_platform,processors,memory_gb,cidr_block_sys_id,cidr_block,vlan_id,data_center,licensing_restrictions,application_info_sys_id,application_info,support_hours,dr_protection,startup_priority,disk_1_os,disk_2_swap_disk,disk_3,disk_4,disk_5,disk_6,disk_7,disk_8,disk_9,disk_10,disk_11,disk_12,disk_13,disk_14,disk_15,disk_16,special_instructions,customer_request,additional_comments) Values ( + '$RitmNum','$RitmSysId','$opened_at','$requested_for','$request_type','$environment','$host_name_ref','$host_name','$server_type','$operating_system','$target_os_version_linux','$target_os_version_windows','$target_platform','$processors','$memory_gb','$cidr_block_sys_id','$cidr_block','$vlan_id','$data_center','$licensing_restrictions','$application_info_sys_id','$application_info','$support_hours','$dr_protection','$startup_priority','$disk_1_os','$disk_2_swap_disk','$disk_3','$disk_4','$disk_5','$disk_6','$disk_7','$disk_8','$disk_9','$disk_10','$disk_11','$disk_12','$disk_13','$disk_14','$disk_15','$disk_16','$special_instructions','$customer_request','$additional_comments' + ) + " + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message $SqlQuery -Verbose + } + Write-Verbose -Message ("End " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + } + Write-Verbose ("End " + $Ritm.number) -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 new file mode 100644 index 0000000..a6b40fc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 @@ -0,0 +1,46 @@ +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] + [string[]] + $VMName, + + [Parameter(Mandatory = $true, ParameterSetName = 'NewBuilds')] + [switch] + $NewBuilds, + + [Parameter(Mandatory = $true, ParameterSetName = 'All')] + [switch] + $All +) + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +switch ($PSCmdlet.ParameterSetName) { + 'VMName' { + Write-Verbose -Message "Parameter Set VMName" -Verbose + $VMs = Get-VM -Name $VMName + } + 'NewBuilds' { + Write-Verbose -Message "Parameter Set NewBuilds" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM + } + 'All' { + Write-Verbose -Message "Parameter Set All" -Verbose + $VMs = Get-VM | Where-Object CreateDate -lt ((Get-Date).AddDays(-2)) + } +} + +ForEach($VM in $VMs){ + try{ + Write-Verbose -Message ("Start " + $VM.Name) -Verbose + Get-VM -Name $VM.Name | Select Uid + Move-ITDVMwareVMToAppNameFolder -VMName $VM.Name -ErrorAction Stop -Verbose + } + catch { + $error[0] + } +} + + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 new file mode 100644 index 0000000..e456f97 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 @@ -0,0 +1,58 @@ +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] + [string[]] + $VMName, + + [Parameter(Mandatory = $true, ParameterSetName = 'NewBuilds')] + [switch] + $NewBuilds, + + [Parameter(Mandatory = $true, ParameterSetName = 'All')] + [switch] + $All +) + +Write-Verbose -Message "Connect to ServiceNow" -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +<#switch ($PSBoundParameters.ContainsKey('VMName')) { + $true { + $VMs = Get-VM -Name $VMName + } + $false { + Write-Verbose -Message "VMName parameter not provided, working on new builds only" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + } +}#> + +switch ($PSCmdlet.ParameterSetName) { + 'VMName' { + Write-Verbose -Message "Parameter Set VMName" -Verbose + $VMs = Get-VM -Name $VMName + } + 'NewBuilds' { + Write-Verbose -Message "Parameter Set NewBuilds" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM + } + 'All' { + Write-Verbose -Message "Parameter Set All" -Verbose + $VMs = Get-VM + } +} + +ForEach($VM in $VMs){ + try{ + Write-Verbose -Message ("Start " + $VM.Name) -Verbose + Set-ITDVMwareVMTagFromCmdb -VMName $VM.Name -ErrorAction Stop -Verbose + } + catch { + $error[0] + } +} + + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 new file mode 100644 index 0000000..6a3edcf --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 @@ -0,0 +1,158 @@ +# loop through them, create sql record + +# $cat_item_sys_id = 'c64e27af47244610b7853238436d435d' +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Prep variable and SQL connection" -Verbose +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = "ServiceNow_RitmDump_ServerBuildRequestV1" + +# get most recent RITM from SQL, get the opened_at value +$SqlQuery = "SELECT [RitmNum],[RitmSysId],[opened_at] FROM [$Database].[dbo].[$Table]" +$SqlExistingRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +$NewestRecord = ($SqlExistingRecords | Sort-Object -Descending opened_at) | select -First 1 +$DateYMDFilter = ($NewestRecord.opened_at | Get-Date -UFormat "%Y-%m-%d") +$DateHMSFilter = ($NewestRecord.opened_at | Get-Date -UFormat "%H:%M:%S") + +#$Filter = "cat_item=c64e27af47244610b7853238436d435d^opened_at>javascript:gs.dateGenerate('2024-07-30','23:59:59')" + +#$Filter = "cat_item=c64e27af47244610b7853238436d435d" +$Filter = "cat_item=c64e27af47244610b7853238436d435d^opened_at>javascript:gs.dateGenerate('$DateYMDFilter','$DateHMSFilter')" +Write-Verbose -Message ("Filter is " + $Filter) -Verbose + +# retrieve list of RITMs created since $opened_at (>opened_at) +Write-Verbose -Message "Retrieve list of RITMs created since last update" -Verbose +#$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter -IncludeTotalCount -IncludeCustomVariable | Sort-Object Number +$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter -IncludeTotalCount -IncludeCustomVariable | Sort-Object Number +#$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number 'RITM0262097' -IncludeCustomVariable +Write-Verbose -Message ("RITMs found: " + @($AllRitms).count) -Verbose + + +ForEach ($Ritm in $AllRitms) { + Write-Verbose ("Start " + $Ritm.number) -Verbose + # get all variable set rows + $VariableSet = (Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -IncludeVariableSet).VariableSet + ForEach ($VSet in $VariableSet) { + Write-Verbose -Message ("Start " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # figure out values + $RitmNum = $Ritm.number.value + $RitmSysId = $Ritm.sys_id.value + $opened_at = $Ritm.opened_at.display_value + $requested_for = $Ritm.requested_for.display_value + $request_type = $Ritm.CustomVariable.request_type.value + $environment = $Ritm.CustomVariable.environment.value + $host_name_ref = $VSet.host_name_ref + $host_name = If ($VSet.host_name_ref) { + (Get-ITDServiceNowRecord -Table cmdb_ci -SysId $VSet.host_name_ref).Name.display_value + } + Else { + $VSet.host_name + } + $server_type = $VSet.server_type + $operating_system = $VSet.operating_system + $target_os_version_linux = $VSet.target_os_version_linux + $target_os_version_windows = $VSet.target_os_version_windows + $target_platform = $VSet.target_platform + $processors = $VSet.processors + $memory_gb = $VSet.memory_gb + $cidr_block_sys_id = $VSet.cidr_block + $cidr_block = (Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId $cidr_block_sys_id).subnet.display_value + $vlan_id = $VSet.vlan_id + $data_center = $VSet.data_center + $licensing_restrictions = $VSet.licensing_restrictions + $application_info_sys_id = $VSet.application_info + $application_info = (Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId $application_info_sys_id).name.display_value + $support_hours = $VSet.support_hours + $dr_protection = $VSet.dr_protection + $startup_priority = $VSet.startup_priority + $disk_1_os = $VSet.disk_1_os + $disk_2_swap_disk = $VSet.disk_2_swap_disk + $disk_3 = $VSet.disk_3 + $disk_4 = $VSet.disk_4 + $disk_5 = $VSet.disk_5 + $disk_6 = $VSet.disk_6 + $disk_7 = $VSet.disk_7 + $disk_8 = $VSet.disk_8 + $disk_9 = $VSet.disk_9 + $disk_10 = $VSet.disk_10 + $disk_11 = $VSet.disk_11 + $disk_12 = $VSet.disk_12 + $disk_13 = $VSet.disk_13 + $disk_14 = $VSet.disk_14 + $disk_15 = $VSet.disk_15 + $disk_16 = $VSet.disk_16 + $special_instructions = $Ritm.CustomVariable.special_instructions.value + $customer_request = $Ritm.CustomVariable.customer_request.value + $additional_comments = $Ritm.CustomVariable.additional_comments.value + + Write-Verbose -Message ("Add to SQL " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # add record to SQL + $SqlQuery = "INSERT INTO [$Table] ( + RitmNum, RitmSysId, opened_at,requested_for,request_type,environment,host_name_ref,host_name,server_type,operating_system,target_os_version_linux,target_os_version_windows,target_platform,processors,memory_gb,cidr_block_sys_id,cidr_block,vlan_id,data_center,licensing_restrictions,application_info_sys_id,application_info,support_hours,dr_protection,startup_priority,disk_1_os,disk_2_swap_disk,disk_3,disk_4,disk_5,disk_6,disk_7,disk_8,disk_9,disk_10,disk_11,disk_12,disk_13,disk_14,disk_15,disk_16,special_instructions,customer_request,additional_comments) Values ( + '$RitmNum','$RitmSysId','$opened_at','$requested_for','$request_type','$environment','$host_name_ref','$host_name','$server_type','$operating_system','$target_os_version_linux','$target_os_version_windows','$target_platform','$processors','$memory_gb','$cidr_block_sys_id','$cidr_block','$vlan_id','$data_center','$licensing_restrictions','$application_info_sys_id','$application_info','$support_hours','$dr_protection','$startup_priority','$disk_1_os','$disk_2_swap_disk','$disk_3','$disk_4','$disk_5','$disk_6','$disk_7','$disk_8','$disk_9','$disk_10','$disk_11','$disk_12','$disk_13','$disk_14','$disk_15','$disk_16','$special_instructions','$customer_request','$additional_comments' + ) + " + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message ("End " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + } + Write-Verbose ("End " + $Ritm.number) -Verbose +} + +<# scratch +Write-Verbose -Message ("Add record to SQL") -Verbose +$SqlQuery = "INSERT INTO [$SnapshotTable] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('$Name', '$StartDateTimeSql', '$RequestedBy', $DurationHours, 'Requested', '$EndDateTimeSql','$Email','$PSUJobId');SELECT SCOPE_IDENTITY();" +#Write-Verbose -Message $SqlQuery -Verbose +$SnapshotId = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:itdpsu1 -Verbose).Column1 + + + + +select TOP (1000) [RitmNum] +, [RitmSysId] +, [opened_at] +, [requested_for] +, [request_type] +, [environment] +, [host_name_ref] +, [host_name] +, [server_type] +, [operating_system] +, [target_os_version_linux] +, [target_os_version_windows] +, [target_platform] +, [processors] +, [memory_gb] +, [cidr_block_sys_id] +, [cidr_block] +, [vlan_id] +, [data_center] +, [licensing_restrictions] +, [application_info_sys_id] +, [application_info] +, [support_hours] +, [dr_protection] +, [startup_priority] +, [disk_1_os] +, [disk_2_swap_disk] +, [disk_3] +, [disk_4] +, [disk_5] +, [disk_6] +, [disk_7] +, [disk_8] +, [disk_9] +, [disk_10] +, [disk_11] +, [disk_12] +, [disk_13] +, [disk_14] +, [disk_15] +, [disk_16] +, [special_instructions] +, [customer_request] +, [additional_comments] +FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1] +#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 new file mode 100644 index 0000000..1376858 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 @@ -0,0 +1,25 @@ +Param( + [string] + $VMName, + + [switch] + $SRMImplemented +) + +Write-Verbose "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro +Write-Verbose "Start Sync" -Verbose + +switch ($PSBoundParameters.Keys){ + 'VMName' { $SyncITDVMwareVMMetadataToSharePointParams += @{VMName = $VMName} } + 'SRMImplemented' { $SyncITDVMwareVMMetadataToSharePointParams += @{SRMImplemented = $SRMImplemented} } +} + +Write-Host $SyncITDVMwareVMMetadataToSharePointParams + +Sync-ITDVMwareVMMetadataToSharePoint @SyncITDVMwareVMMetadataToSharePointParams -Verbose +#Write-Output $VMName +Write-Verbose "End Sync" + +Write-Verbose "Disconnect vCenter" +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 new file mode 100644 index 0000000..ef2625d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 @@ -0,0 +1,10 @@ +Write-Verbose -Message "Connect to ServiceNow" -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +Write-Verbose -Message "Execute Sync-ITDVMareVMTagsFromCmdb" -Verbose +Sync-ITDVMwareVMTagsFromCmdb -Verbose + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 new file mode 100644 index 0000000..a6691e9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 @@ -0,0 +1,2 @@ +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred +Update-ITDSNowVMTaskDescription -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Get-HelloWorld.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Get-HelloWorld.ps1 new file mode 100644 index 0000000..c4cf542 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Get-HelloWorld.ps1 @@ -0,0 +1,21 @@ +<#Param( + [string] + $SCTaskNum = "World" +) + +Write-Host "Hello, $WorldName!"#> + + +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + $NewVMParams = @{ + Name = "itdzmtest"+(100..999 | Get-Random) + ".nd.gov" + ResourcePool = "WINDOWS1" + Datastore = "WINDOWS1_FS92_Gen"; + DiskStorageFormat = "Thin"; + Template = "Windows Server 2022 Standard 2108.21"; + Location = Get-Cluster "WINDOWS1" | Get-Datacenter | Get-Folder -Name "_New Builds" + } + + New-VM @NewVMParams + Disconnect-ITDvCenter + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/New-TestNestedInvoke.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/New-TestNestedInvoke.ps1 new file mode 100644 index 0000000..da71eaa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/New-TestNestedInvoke.ps1 @@ -0,0 +1,152 @@ +<# +.SYNOPSIS + Processes automated server build tasks for Windows machines in ServiceNow, triggered via PowerShell Universal. +.DESCRIPTION + This script connects to the ServiceNow API, retrieves open catalog tasks that match a specific filter for automated server build tasks, + and processes them. This script is designed to run as a scheduled task. It can optionally filter tasks by a specific SCTask number. +.PARAMETER SCTaskNum + The ServiceNow task number to filter the tasks. If not provided, all tasks matching the filter will be processed. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 + This example runs the script and processes all open tasks that match the filter for automated server build tasks. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 -SCTaskNum 'SCTASK0012345' + This example runs the script and processes only the task with the specified SCTask number. +.NOTES + Ensure that the ServiceNow instance URL and credentials are correctly configured in the New-ITDServiceNowSession function. + This script is not supported in Linux. +#> +<# +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number | Select-Object -First 3 +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + { $_ -match "human review" } { + Write-Verbose -Message "Human review required, skipping" -Verbose + Break + } + { $_ -match "build step 2 complete" } { + # execute Step 3 + Write-Verbose -Message "Step 2 already complete, starting step 3" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + #$WorkNotesMsg = ("VMware build Step 3 started.`nPSU Job Id #" + $PSUJob.Id) + Break + } + { $_ -match "build Step 2 started"} { + Write-Verbose -Message "Step 2 already started, skipping" -Verbose + Break + } + { $_ -match "build step 1 complete" } { + # execute Step 2 + Write-Verbose -Message "Step 1 already complete, starting Step 2" -Verbose + # Determine if VMware or Azure and run appropriate build Step 2 function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 2" -Verbose + #Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step2.ps1" -SCTaskNum $SCTaskNum + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + { $_ -match "build Step 1 started"} { + Write-Verbose -Message "Step 1 already started, skipping" -Verbose + Break + } + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + If($null -eq $WorkNotesMsg){ + # do nothing + } Else { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{work_notes = $WorkNotesMsg } + } +} + +#> + +#Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot02.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot03.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot04.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot05.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot06.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot07.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot08.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot09.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot10.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot11.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot12.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot13.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot14.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot15.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-AzIaaSCredential.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-AzIaaSCredential.ps1 new file mode 100644 index 0000000..05a4a39 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-AzIaaSCredential.ps1 @@ -0,0 +1,6 @@ +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDSchedule.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDSchedule.ps1 new file mode 100644 index 0000000..c8db344 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDSchedule.ps1 @@ -0,0 +1,77 @@ +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + <# + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } +#> + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + #$PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + + Write-Verbose -Message "End $SCTaskNum" -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDScheduleWithCreds.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDScheduleWithCreds.ps1 new file mode 100644 index 0000000..83c5bda --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ITDScheduleWithCreds.ps1 @@ -0,0 +1,11 @@ +# It all starts with a single line of powershell code. + +Write-Warning -Message ("Secret direct: " + $Secret:ndgov_svcitdvmhpe.username) + +$vaultcred = Get-ITDPassword -Title "IaaS Automation Account" -UserName "ndgov\svcitdiaasauto" + +Write-Warning -Message ("Secret vault: " + $vaultcred.username) + +$vaultcred2 = Get-ITDPassword -Title "VMware iLO Service Account" -UserName "ndgov\svcitdvmhpe" + +Write-Warning -Message ("Secret vault: " + $vaultcred2.username) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-InvokeZM.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-InvokeZM.ps1 new file mode 100644 index 0000000..4a5e672 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-InvokeZM.ps1 @@ -0,0 +1,5 @@ +$x=Invoke-PSUScript -Name Get-HelloWorld.ps1 -WorldName "zm" +Write-Warning $x.Id + +$x=Invoke-PSUScript -Name Get-HelloWorld.ps1 -WorldName "zo" +Write-Warning $x.Id diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-PSUVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-PSUVariable.ps1 new file mode 100644 index 0000000..808484f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-PSUVariable.ps1 @@ -0,0 +1,2 @@ +# It all starts with a single line of powershell code. +Write-Verbose -Message $Secret:ndgov_svcitdpsuwin.username -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMFile.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMFile.ps1 new file mode 100644 index 0000000..75d1dc5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMFile.ps1 @@ -0,0 +1,16 @@ +param ( + # [Parameter(Mandatory = $true, + # HelpMessage = "CRC TEXT ONLY")] + # [string] + # $CSR, + [Parameter(Mandatory = $true, + HelpMessage = "CRC File")] + [file] + $CSRfile + ) + + + #$csr=Get-Content -raw $Csrfile + $csr = [Text.Encoding]::UTF8.GetString($CSRfile.Content) + + Write-Host $csr \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMVariable.ps1 new file mode 100644 index 0000000..c20076c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/Test-ZMVariable.ps1 @@ -0,0 +1,16 @@ + +Param( + + [ValidateScript( {$_ -in @($zmtest) } )] + [string] + $variable1, + + [ValidateSet( '1000','1001','1002','1003','1004','1005','1006','1007','1008','1009','1010','1011','1012','1013','1014','1015','1016','1017','1018','1019','1020','1021','1022','1023','1024','1025','1026','1027','1028','1029','1030','1031','1032','1033','1034','1035','1036','1037','1038','1039','1040','1041','1042','1043','1044','1045','1046','1047','1048','1049','1050','1051','1052','1053','1054','1055','1056','1057','1058','1059','1060','1061','1062','1063','1064','1065','1066','1067','1068','1069','1070','1071','1072','1073','1074','1075','1076','1077','1078','1079','1080','1081','1082','1083','1084','1085','1086','1087','1088','1089','1090','1091','1092','1093','1094','1095','1096','1097','1098','1099','1100' + ) ] + [string] + $variable2 +) + + +write-warning $variable1 +write-host $variable2 \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/test-sql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/test-sql.ps1 new file mode 100644 index 0000000..0b29182 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/ZM-Test/test-sql.ps1 @@ -0,0 +1,18 @@ + + switch ($env:computername) { + "ITDWINAUTOT1" { + New-UDTypography -Text 'NPD' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } + "ITDWINAUTOP1" { + New-UDTypography -Text 'PRD' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } + } + + $SqlQuery = "SELECT [PSUJobId],[DateTime],[ComputerName],[Status],[FullName] FROM [$Database].[dbo].[$Table]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 new file mode 100644 index 0000000..88924ce --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 @@ -0,0 +1,25 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + switch($env:computername){ + "ITDWINAUTOT1" { + New-UDListItem -Label 'Remove-ITDExpiredFiles Log' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + } + "ITDWINAUTOP1" { + New-UDListItem -Label 'Remove-ITDExpiredFiles Log' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } + } + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + switch($env:computername){ + "ITDWINAUTOT1" { Get-UDPage -Name 'NPD' } + "ITDWINAUTOP1" { Get-UDPage -Name 'PRD' } + } +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 new file mode 100644 index 0000000..d37f42e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 @@ -0,0 +1,30 @@ +New-UDPage -Url "/PRD" -Name "PRD" -Content { +New-UDTypography -Text 'Remove Expired Files Log' + +switch($env:COMPUTERNAME){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } +} + + $SqlQuery = "SELECT [PSUJobId],[DateTime],[ComputerName],[Status],[FullName] FROM [$Database].[dbo].[$Table]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'PSUJobId' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' -ShowFilter + New-UDTableColumn -Property 'ComputerName' -Title 'ComputerName' -ShowFilter + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'FullName' -Title 'FullName' -ShowFilter + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Title "PRD" -Icon @{ + id = 'd0f3391d-efa6-4210-b4dd-ef0cad028382' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 new file mode 100644 index 0000000..f2d6d03 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 @@ -0,0 +1,30 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + switch($env:computername){ + "ITDWINAUTOT1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_NPD' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + } + "ITDWINAUTOP1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_PRD' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } + } + } + + New-UDListItem -Label 'Live Snapshots' -OnClick { + Invoke-UDRedirect -Url '/LiveSnapshots' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + switch($env:computername){ + "ITDWINAUTOT1" { Get-UDPage -Name 'NPD' } + "ITDWINAUTOP1" { Get-UDPage -Name 'PRD' } + } + Get-UDPage -Name 'LiveSnapshots' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 new file mode 100644 index 0000000..e1303ac --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 @@ -0,0 +1,57 @@ +New-UDPage -Url "/PRD" -Name "PRD" -Content { +New-UDTypography -Text 'PRD' + <#New-UDForm -Content { + + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextBox -Label "VMName" -Id VMName + New-UDTextBox -Label "DateTime" -Id DateTime + New-UDTextBox -Label "DurationHours" -Id DurationHours + New-UDTextBox -Label "Email" -Id Email + } + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDVMwareSnapshotTask.ps1' + VMName = $EventData.VMName; + DateTime = $EventData.DateTime; + DurationHours = $EventData.DurationHours; + Email = $EventData.Email + } + $InvokePSUScriuptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("attempting snapshot") + } #> + +switch($env:COMPUTERNAME){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[PSUJobIdRequest],[PSUJobIdDelete],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [$Database].[dbo].[$SnapshotTable]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'Id' -Title 'Id' -ShowFilter + New-UDTableColumn -Property 'VMName' -Title 'VMName' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' + New-UDTableColumn -Property 'RequestedBy' -Title 'RequestedBy' -ShowFilter + New-UDTableColumn -Property 'DurationHours' -Title 'DurationHours' + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'NotifyEmail' -Title 'NotifyEmail' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdRequest' -Title 'PSUJobIDRequest' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdDelete' -Title 'PSUJobIDDelete' -ShowFilter + New-UDTableColumn -Property 'TakenDateTime' -Title 'TakenDateTime' + New-UDTableColumn -Property 'ExpireDateTime' -Title 'ExpireDateTime' + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Title "PRD" -Icon @{ + id = 'd0f3391d-efa6-4210-b4dd-ef0cad028382' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/Infra-VMware_Snapshot/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 new file mode 100644 index 0000000..cc997dc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 @@ -0,0 +1,13 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'AD Service Accounts' -OnClick { + Invoke-UDRedirect -Url '/ADServiceAccount' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'ADServiceAccount' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 new file mode 100644 index 0000000..ccb8238 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 @@ -0,0 +1,34 @@ +New-UDPage -Url "/ADServiceAccount" -Name "ADServiceAccount" -Content { +New-UDTypography -Text 'ADServiceAccount' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SqlQuery = "SELECT TOP (1000) [RequestedBy] + ,[PSUJobId] + ,[SamAccountName] + ,[Description] + ,[PasswordstateTitle] + ,[PasswordstateList] + ,[SnowCHGNum] + ,[Status] + ,[DomainName] + ,[DateTime] + FROM [ITD-Systems-Automation].[dbo].[Infra_ActiveDirectory_Object_NewITDADServiceAccount_PRD] + ORDER BY [DateTime] DESC" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'PSUJobId' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' -ShowFilter + New-UDTableColumn -Property 'RequestedBy' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'SamAccountName' -Title 'SamAccountName' -ShowFilter + New-UDTableColumn -Property 'PasswordstateList' -Title 'PasswordstateList' -ShowFilter + New-UDTableColumn -Property 'PasswordstateTitle' -Title 'PasswordstateTitle' -ShowFilter + New-UDTableColumn -Property 'SnowCHGNum' -Title 'SnowCHGNum' -ShowFilter + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'Domainname' -Title 'DomainName' -ShowFilter + + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Icon @{ + type = 'icon' + id = '259b4c05-17df-4440-9907-57ab4df1e6c9' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/NewITDADServiceAccount/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/PSUVariableReview.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/PSUVariableReview.ps1 new file mode 100644 index 0000000..3c1ab69 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/PSUVariableReview.ps1 @@ -0,0 +1,17 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -Icon (New-UDIcon -Icon Home) -OnClick { + Invoke-UDRedirect -Url '/home' + } + New-UDListItem -Label 'Users' -Icon (New-UDIcon -Icon User) -OnClick { + Invoke-UDRedirect -Url '/users' + } + New-UDListItem -Label 'Groups' -Icon (New-UDIcon -Icon Users) -OnClick { + Invoke-UDRedirect -Url '/groups' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' + Get-UDPage -Name 'users' + Get-UDPage -Name 'groups' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/Users.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/Users.ps1 new file mode 100644 index 0000000..8bd127c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/Users.ps1 @@ -0,0 +1,26 @@ +New-UDPage -Url "/Users" -Name "Users" -Content { +New-UDTypography -Text 'Roles assigned to this user:' +New-UDList -Content { + $Roles | ForEach-Object{ + New-UDListItem -Label $_ + } +} + + +New-UDTypography -Text 'Variables this user can access:' +$AllPSUVariables = Get-PSUVariable +$TableData = $AllPSUVariables | Select *,@{n='RoleStr';e={$_.Role -join ", "}},@{n='SecretValue';e={$SecretValue=Get-Childitem ("Secret:" + $_.Name) -ErrorAction SilentlyContinue;If($SecretValue -is [string]){"secure_string"}Else{$SecretValue}}},@{n='SecretUsername';e={(Get-Childitem ("Secret:" + $_.Name) -ErrorAction SilentlyContinue).Username}} + +New-UDTable -Columns @( + New-UDTableColumn -Property 'Name' -Title 'Name' -ShowFilter + New-UDTableColumn -Property 'RoleStr' -Title 'Role' -ShowFilter + New-UDTableColumn -Property 'Type' -Title 'Type' -ShowFilter + New-UDTableColumn -Property 'Value' -Title 'Value' -ShowFilter + New-UDTableColumn -Property 'Secret' -Title 'Secret' -ShowFilter + New-UDTableColumn -Property 'SecretValue' -Title 'SecretValue' -ShowFilter + New-UDTableColumn -Property 'SecretUsername' -Title 'SecretUsername' -ShowFilter + ) -Data $TableData -Dense +} -Title "Users" -Icon @{ + type = 'icon' + id = '37c13667-6c5a-4cb1-a16b-49eaddd96d03' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/PSUVariableReview/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 new file mode 100644 index 0000000..690ff2c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 @@ -0,0 +1,3 @@ +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/RemoveITDExpiredFiles/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/ServiceNow.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/ServiceNow.ps1 new file mode 100644 index 0000000..c26add3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/ServiceNow.ps1 @@ -0,0 +1,33 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'Server Build Request V1 (Current) Lookup' -OnClick { + Invoke-UDRedirect -Url '/ServerBuildRequestV1' + } + New-UDListItem -Label 'Application Server V2 (Previous) Lookup' -OnClick { + Invoke-UDRedirect -Url '/ApplicationServerV2' + } + New-UDListItem -Label 'CMDB Ci Lookup' -OnClick { + Invoke-UDRedirect -Url '/CMDBServerList' + } + New-UDListItem -Label 'AppNameLookup' -OnClick { + Invoke-UDRedirect -Url '/AppNameLookup' + } + New-UDListItem -Label 'CiLookup' -OnClick { + Invoke-UDRedirect -Url '/CiLookup' + } + New-UDListItem -Label 'AzureSizeHelper' -OnClick { + Invoke-UDRedirect -Url '/AzureVmSizeHelper' + } +) +AppNameLookup.ps1 - /AppNameLookup +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'CMDBServerList' + Get-UDPage -Name 'ServerBuildRequestV1' + Get-UDPage -Name 'ApplicationServerV2' + Get-UDPage -Name 'AppNameLookup' + Get-UDPage -Name 'CiLookup' + Get-UDPage -Name 'AzureVmSizeHelper' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AppNameLookup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AppNameLookup.ps1 new file mode 100644 index 0000000..0834d7d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AppNameLookup.ps1 @@ -0,0 +1,58 @@ +New-UDPage -Url "/AppNameLookup" -Name "AppNameLookup" -Content { +New-UDTypography -Id "disclaimer" -Text "This is querying the cmdb_ci_service_auto table in ServiceNow. This is live data being shown." + + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $PropertyList = @( + @{ + name = "name"; + expression = { $_.name.display_value }; + }, + @{ + name = "sys_id"; + expression = { $_.sys_id.value } ; + }, + @{ + name = "u_primary_systems_admin"; + expression = { $_.u_primary_systems_admin.display_value } ; + }, + @{ + name = "u_secondary_systems_admin"; + expression = { $_.u_secondary_systems_admin.display_value } ; + }, + @{ + name = 'u_systems_owner'; + expression = { $_.u_systems_owner.display_value}; + } + ) + #$Result = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("nameLIKE" + $EventData.CiName) -IncludeTotalCount | Select-Object -Property $PropertyList + $GetITDServiceNowRecordParams = @{ + Table = 'cmdb_ci_service_auto'; + IncludeTotalCount = $true; + Fields = @( + 'name', + 'sys_id', + 'u_primary_systems_admin', + 'u_secondary_systems_admin', + 'u_systems_owner' + ) + } + $Result = Get-ITDServiceNowRecord @GetITDServiceNowRecordParams | Select-Object -Property $PropertyList + $CmdbCiUrl = "https://northdakota.service-now.com/nav_to.do?uri=" + $Result.sys_class_name + ".do?sys_id=" + $Result.sys_id + + New-UDTable -Columns @( + New-UDTableColumn -Property 'SNowUrl' -Title 'CmdbCiUrl' -Render { #https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_win_server.do?sys_id=8bc3ecd11b0154509d7ada01dd4bcb59 + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_service_auto.do?sys_id=" + $EventData.sys_id) -Id "lnkSNow" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + New-UDTableColumn -Property 'name' -Title 'name' -ShowSort -ShowFilter + #New-UDTableColumn -Property 'sys_id' -Title 'sys_id' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_primary_systems_admin' -Title 'u_primary_systems_admin' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_secondary_systems_admin' -Title 'u_secondary_systems_admin' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_systems_owner' -Title 'u_systems_owner' -ShowSort -ShowFilter + ) -Data ($Result | sort-object Name) -ShowPagination -Dense -PageSize 50 +} -Title "AppNameLookup" -Icon @{ + id = '9fdceac8-807e-4d5e-acda-3d477d77fdb4' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 new file mode 100644 index 0000000..5ca0959 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 @@ -0,0 +1,25 @@ +New-UDPage -Url "/ApplicationServerV2" -Name "ApplicationServerV2" -Content { +New-UDTypography -Text 'Application Server request items (RITMs) submitted between 2023/02/27 and 2024/06/25 in which the field "VM Work Needed" is set to "Yes"' + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = 'ServiceNow_RitmDump_ApplicationServerV2' + + $SqlQuery = "SELECT [number],[sys_id],[opened_at],[requested_for],[short_description],[request_type],[application_name],[environment],[additional_comments],[vm_work_needed],[server_name],[host_name],[server_type],[operating_system],[target_platform],[processors],[memory_gb],[cidr_block],[data_center],[licensing_restrictions],[agency_name],[application_info],[support_hours],[dr_protection],[startup_priority],[disk_1_os],[disk_2_swap_disk],[disk_3],[disk_4],[disk_5],[disk_6],[disk_7],[disk_8],[disk_9],[disk_10],[disk_11],[disk_12],[disk_13],[disk_14],[disk_15],[disk_16] FROM [$Database].[dbo].[$Table] WHERE vm_work_needed = '1'" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'number' -Title 'number' -ShowSort + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' + New-UDTableColumn -Property 'server_name' -Title 'server_name' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter + ) -Data ($SqlRecords | Select *,@{n='Open';e={$_.sys_id}} | Sort-Object -Descending number) -Dense -ShowPagination -PageSize 20 +} -Title "ApplicationServerV2" -Icon @{ + id = 'd9dc64f6-9f4b-432a-866a-d3189529528b' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 new file mode 100644 index 0000000..b0ea0b4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 @@ -0,0 +1,23 @@ +New-UDPage -Url "/AzureVmSizeHelper" -Name "AzureVmSizeHelper" -Content { +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +$TableData = Get-AzVmSize -Location centralus | Select *,` + @{n='MemoryInGB';e={$_.MemoryInMb / 1024}}, ` + @{n='OSDiskSizeInGB'; e={$_.OsDiskSizeInMb / 1024}}, ` + @{n='ResourceDiskSizeInGB'; e={$_.ResourceDiskSizeInMB / 1024}} | Sort-Object NumberOfCores,MemoryInGB + +New-UDTable -Columns @( + New-UDTableColumn -Property 'Name' -Title 'Name' -ShowSort -ShowFilter + New-UDTableColumn -Property 'NumberOfCores' -Title 'NumberOfCores' -ShowSort -ShowFilter + New-UDTableColumn -Property 'MemoryInGB' -Title 'MemoryInGB' -ShowFilter -ShowSort + New-UDTableColumn -Property 'OSDiskSizeInGB' -Title 'OSDiskSizeInGB' -ShowFilter -ShowSort + New-UDTableColumn -Property 'ResourceDiskSizeInGB' -Title 'ResourceDiskSizeInGB' -ShowFilter -ShowSort +) -Data $TableData -Dense +} -Title "AzureVmSizeHelper" -Icon @{ + type = 'icon' + id = 'f45c0541-5f78-4c00-899b-548e1bbabb04' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CMDBServerList.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CMDBServerList.ps1 new file mode 100644 index 0000000..e7fd3bd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CMDBServerList.ps1 @@ -0,0 +1,154 @@ +New-UDPage -Url "/CMDBServerList" -Name "CMDBServerList" -Content { +# Use Get-UDPage -Name 'CmdbServer' to use this page in your dashboard + +<# + New-UDCard -Content { + New-UDList -children { + New-UDListItem -Label "Enter the Name of the Cmdb Ci. Usually host name, not FQDN. `nFor example: itdsccmp2.nd.gov, enter itdsccmp2. The search is using 'LIKE' comparsion operator, so wildcards are automatically applied at both sides of the entered value. " + New-UDListItem -Label 'This search is a live query of the ServiceNow Cmdb.' + New-UDListItem -Label 'This is a work in progress. Use at your own discretion.' + } + }#> + + + + +New-UDForm -Id 'CiLookup' -Content { + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Id 'CiName' + } + } +} -OnValidate { + $FormContent = $EventData + if ($FormContent.CiName -eq $null -or $FormContent.VMName -eq '') { + New-UDFormValidationResult -ValidationError "CiName is required" + } + else { + New-UDFormValidationResult -Valid + } +} -OnSubmit { + Show-UDToast -Message ("Querying ServiceNow table cmdb_ci_server for record with name " + $EventData.Name) -Duration 20000 + + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $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_application_svc"; + expression = { $_.u_nd_application_svc.display_value } + }, + @{ + name = "u_nd_licensing_restrictions"; + expression = { $_.u_nd_licensing_restrictions.display_value } + }, + @{ + name = "u_support_hours"; + expression = { $_.u_support_hours.display_value } + }, + @{ + name = "u_nd_dr_protection"; + expression = { $_.u_nd_dr_protection.display_value }; + }, + @{ + name = "u_srm_recovery_type"; + expression = { $_.u_srm_recovery_type.display_value } + }, + @{ + name = "os"; + expression = { $_.os.display_value } + }, + @{ + name = "os_version"; + expression = { $_.os_version.display_value } + }, + @{ + name = "model_id"; + expression = { $_.model_id.display_value } + } + ) + #$Result = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("nameLIKE" + $EventData.CiName) -IncludeTotalCount | Select-Object -Property $PropertyList + $GetITDServiceNowRecordParams = @{ + #Filter = "model_id=3161ee6c1bf810502653997fbd4bcb4c^ORmodel_id%253Da75f244c1bd75014bba0113fad4bcb72" + Filter = "model_idLIKEVMware^ORmodel_idLIKEMicrosoft" + Table = 'cmdb_ci_server'; + IncludeTotalCount = $true; + Fields = @( + 'name', + 'sys_id', + 'dns_domain', + 'sys_class_name', + 'operational_status', + 'environment', + 'u_nd_type', + 'model_id', + 'os', + 'os_version', + 'u_nd_application_svc', + 'u_nd_licensing_restrictions', + 'u_nd_dr_protection', + 'u_srm_recovery_type', + 'u_support_hours' + ) + } + $Result = Get-ITDServiceNowRecord @GetITDServiceNowRecordParams | Select-Object -Property $PropertyList + $CmdbCiUrl = "https://northdakota.service-now.com/nav_to.do?uri=" + $Result.sys_class_name + ".do?sys_id=" + $Result.sys_id + + New-UDTable -Columns @( + New-UDTableColumn -Property 'CmdbCiUrl' -Title 'CmdbCiUrl' -Render { #https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_win_server.do?sys_id=8bc3ecd11b0154509d7ada01dd4bcb59 + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=" + $EventData.sys_class_name + ".do?sys_id=" + $EventData.sys_id) -Id "lnkCmdbCi" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + New-UDTableColumn -Property 'name' -Title 'name' -ShowSort -ShowFilter + New-UDTableColumn -Property 'dns_domain' -Title 'dns_domain' -ShowFilter + New-UDTableColumn -Property 'u_nd_application_svc' -Title 'u_nd_application_svc' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableCOlumn -Property 'operational_status' -Title 'operational_status' -ShowFilter + New-UDTableColumn -Property 'u_nd_type' -Title 'u_nd_type' -ShowFilter + #New-UDTableColumn -Property 'model_id' -Title 'model_id' -ShowFilter + #New-UDTableColumn -Property 'os' -Title 'os' -ShowFilter + #New-UDTableColumn -Property 'os_version' -Title 'os_version' -ShowFilter + New-UDTableColumn -Property 'u_nd_licensing_restrictions' -Title 'u_nd_licensing_restrictions' -ShowFilter + New-UDTableColumn -Property 'u_support_hours' -Title 'u_support_hours' -ShowFilter + New-UDTableColumn -Property 'u_nd_dr_protection' -Title 'u_nd_dr_protection' -ShowFilter + New-UDTableColumn -Property 'u_srm_recovery_type' -Title 'u_srm_recovery_type' -ShowFilter + ) -Data ($Result | sort-object Name) -ShowPagination -Dense -PageSize 50 + + +} -OnProcessing { + +} + + +New-UDCard -Id 'Result' +} -Title "CMDBServerList" -Icon @{ + id = 'dc0de7d9-022b-4e24-a7c7-7f0e59710542' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiLookup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiLookup.ps1 new file mode 100644 index 0000000..832677d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiLookup.ps1 @@ -0,0 +1,97 @@ +New-UDPage -Url "/CiLookup" -Name "CiLookup" -Content { +New-UDGrid -Container -Children { + New-UDGrid -Item -ExtraSmallSize 4 -Children { + New-UDCard -Title "General Information" -Content { + #New-UDButton -Text "Button 1" + New-UDRow -Columns { + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "Name" -Id "Name" -Value "itddefghijklmno.ndcloud.gov" -FullWidth + } + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "LicensingRestrictions" -Id "LicensingRestrictions" -Value "Microsoft SQL Enterprise" + } + } + } + + } + New-UDGrid -Item -ExtraSmallSize 4 -Children { + New-UDCard -Title "Support Information" -Content { + #New-UDButton -Text "Button 2" + New-UDRow -Columns { + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "AppName" -Id "AppName" + } + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "Support Hours" -Id "Support Hours" + } + } + } + } + } -Id "GridGeneral" + +New-UDContainer -Content { + New-UDLayout -Columns 2 - -Content { + #New-UDTypography "Row 1, Col 1" + New-UDTextBox -Label "Name" -Value "itddefghijklmno.ndcloud.gov" -FullWidth + #New-UDTypography "Row 1, Col 2" + New-UDTextBox -Label "AppName" -Value "Infra-POS-SomeStupidApp" -FullWidth + New-UDTypography "Row 2, Col 1" + New-UDTypography "Row 2, Col 2" + } + } + +$tablePwd = [ordered]@{ + 'Password Expiration' = "itdsomething.nd.gov" + 'Account Expiration' = "ITD-POS-StupidName" + 'Last Logon Timestamp' = "Microsoft SQL Enterperise" +} + + +$Data = , @($tablePwd.GetEnumerator()) +$DateColumns = @( +New-UDTableColumn -Property Name -Title " " +New-UDTableColumn -Property Value -Title " " +) +New-UDTable -Id "PasswordInfo" -Title "Password and Account Info" -Data $Data[0] -Columns $DateColumns -Dense + + + + + + + +New-UDButton -Text 'Full Width' -OnClick { + Show-UDModal -Content { + New-UDGrid -Container -Children { + New-UDCard -Title "General" -Content { + New-UDElement -Tag 'div' -Id 'addElement' + New-UDTextBox -Id "Name" -Label "Name" -Value "servernamehere.nd.gov" + New-UDTextBox -Id "Operational Status" -Label "Status" -Value "Operational" + New-UDTextBox -Id "AppName" -Label "AppName" -Value "ITD-POS-StupidNameHere" + New-UDTextBox -Id "Support Hours" -Label "Support Hours" -Value "All Day Every Day" + } + New-UDCard -Title "Hardware" -Content { + New-UDTextBox -Id "Datacenter" -Label "Datacenter" -Value "Bismarck" + New-UDTextBox -Id "Environment" -Label "Environment" -Value "Production" + New-UDTextBox -Id "DR Protection" -Label "DR Protection" -Value "VMware: RPO 04:00" + New-UDTextBox -Id "Datacenter" -Label "Datacenter" -Value "Bismarck" + New-UDTextBox -Id "Environment" -Label "Environment" -Value "Production" + New-UDTextBox -Id "DR Protection" -Label "DR Protection" -Value "VMware: RPO 04:00" + New-UDTextBox -Id "OperatingSystem" -Label "Operating System" -Value "Windows Server 2022" + New-UDTextBox -Id "CPU" -Label "CPU" -Value "4" + New-UDTextBox -Id "MemoryGB" -Label "MemoryGB" -Value "12" + New-UDTextBox -Id "DiskGB" -Label "DiskGB" -Value "1197" + } + New-UDCard -Title "Software" -Content { + New-UDTextBox -Id "LicensingRestrictions" -Label "LicensingRestrictions" -Value "Microsoft SQL Enterprise" + New-UDTextBox -Id "OperatingSystem" -Label "Operating System" -Value "Windows Server 2022" + } + } + + #New-UDDynamic + } -FullWidth -MaxWidth 'md' +} +} -Title "CiLookup" -Icon @{ + id = '3743b2ed-0278-4678-8a47-e22ad4514afb' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiTest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiTest.ps1 new file mode 100644 index 0000000..6306b88 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/CiTest.ps1 @@ -0,0 +1,4 @@ +New-UDPage -Url "/CiTest" -Name "CiTest" -Content { + +} -Title "CiTest" -Icon @{ + } -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 new file mode 100644 index 0000000..2f12b45 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 @@ -0,0 +1,39 @@ +New-UDPage -Url "/ServerBuildRequestV1" -Name "ServerBuildRequestV1" -Content { +New-UDTypography -Text "`nServer Build Request request items (RITMs) submitted after 2024/06/25" + +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = 'ServiceNow_RitmDump_ServerBuildRequestV1' + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$SqlQuery = "SELECT [RitmNum], + [RitmSysId], + [opened_at], + [requested_for], + [request_type], + [environment] + ,[host_name_ref] + ,[host_name] + FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1]" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + + +New-UDTable -Dense -ShowPagination -PageSize 20 -Size small -Data ($SqlRecords | Sort-Object -Descending opened_at) -Columns @( + New-UDTableColumn -Property 'RitmUrl' -Title 'RitmUrl' -Render { + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=sc_req_item.do?sys_id=" + $EventData.RitmSysId) -Id "lnkRitm" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + + New-UDTableColumn -Property 'RitmNum' -Title 'RitmNum' -ShowFilter + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + #New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter +) +} -Title "ServerBuildRequestV1" -Icon @{ + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/home.ps1 new file mode 100644 index 0000000..b2d9d89 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNow/pages/home.ps1 @@ -0,0 +1,11 @@ +New-UDPage -Url "/Home" -Name "Home" -Content { +New-UDTypography -text 'Use left side navigation to view various ServiceNow queries' -id 'homeText' -noWrap +} -Generated -Layout ( +New-UDPageLayout -Large @( + New-UDItemLayout -Id 'homeText' -Row 0 -Column 0 -RowSpan 1 -ColumnSpan 1 +) -Medium @( +) -Small @( +) -ExtraSmall @( +) -ExtraExtraSmall @( + ) +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 new file mode 100644 index 0000000..d087b25 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 @@ -0,0 +1,21 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'ServerBuildRequestV1' -OnClick { + Invoke-UDRedirect -Url '/ServerBuildRequestV1' + } + New-UDListItem -Label 'ApplicationServerV2' -OnClick { + Invoke-UDRedirect -Url '/ApplicationServerV2' + } + New-UDListItem -Label 'SpCmdbCompare' -OnClick { + Invoke-UDRedirect -Url '/SpCmdbCompare' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'ApplicationServerV2' + Get-UDPage -Name 'ServerBuildRequestV1' + Get-UDPage -Name 'SpCmdbCompare' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 new file mode 100644 index 0000000..f01d71b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 @@ -0,0 +1,25 @@ +New-UDPage -Url "/ApplicationServerV2" -Name "ApplicationServerV2" -Content { +New-UDTypography -Text 'Application Server request items (RITMs) submitted between 2023/02/27 and 2024/06/25 in which the field "VM Work Needed" is set to "Yes"' + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = 'ServiceNow_RitmDump_ApplicationServerV2' + + $SqlQuery = "SELECT [number],[sys_id],[opened_at],[requested_for],[short_description],[request_type],[application_name],[environment],[additional_comments],[vm_work_needed],[server_name],[host_name],[server_type],[operating_system],[target_platform],[processors],[memory_gb],[cidr_block],[data_center],[licensing_restrictions],[agency_name],[application_info],[support_hours],[dr_protection],[startup_priority],[disk_1_os],[disk_2_swap_disk],[disk_3],[disk_4],[disk_5],[disk_6],[disk_7],[disk_8],[disk_9],[disk_10],[disk_11],[disk_12],[disk_13],[disk_14],[disk_15],[disk_16] FROM [$Database].[dbo].[$Table] WHERE vm_work_needed = '1'" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'number' -Title 'number' -ShowSort + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' + New-UDTableColumn -Property 'server_name' -Title 'server_name' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter + ) -Data ($SqlRecords | Select *,@{n='Open';e={$_.sys_id}} | Sort-Object -Descending number) -Dense -ShowPagination -PageSize 20 +} -Icon @{ + type = 'icon' + id = 'e91ed4ef-cecd-448a-9204-2b453db9db03' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 new file mode 100644 index 0000000..de5ff32 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 @@ -0,0 +1,42 @@ +New-UDPage -Url "/ServerBuildRequestV1" -Name "ServerBuildRequestV1" -Content { + +New-UDTypography -Text "`nServer Build Request request items (RITMs) submitted after 2024/06/25" + +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = 'ServiceNow_RitmDump_ServerBuildRequestV1' + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$SqlQuery = "SELECT [RitmNum], + [RitmSysId], + [opened_at], + [requested_for], + [request_type], + [environment] + ,[host_name_ref] + ,[host_name] + FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1]" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + + +New-UDTable -Dense -ShowPagination -PageSize 20 -Size small -Data ($SqlRecords | Sort-Object -Descending opened_at) -Columns @( + New-UDTableColumn -Property 'RitmUrl' -Title 'RitmUrl' -Render { + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=sc_req_item.do?sys_id=" + $EventData.RitmSysId) -Id "lnkRitm" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + + New-UDTableColumn -Property 'RitmNum' -Title 'RitmNum' -ShowFilter + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + #New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter +) +} -Icon @{ + id = '7d67b921-68aa-4085-84e8-025e92671771' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/dashboards/ServiceNowDumps/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/%ProgramData%/UniversalAutomation/database.db b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/%ProgramData%/UniversalAutomation/database.db new file mode 100644 index 0000000..e69de29 diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/accessControls.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/accessControls.ps1 new file mode 100644 index 0000000..454a01b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/accessControls.ps1 @@ -0,0 +1,27 @@ +##### Teams Used for entire vertical teams, not specific applications, systems, or products +New-PSUAccessControl -Role "Team-Windows" -Tag "Team-Windows_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "Team-Windows" -Tag "Team-Windows_Modify" -Type "View, Edit, Create, Delete, Execute" + +New-PSUAccessControl -Role "Team-Network" -Tag "Team-Network_Execute" -Type "View, Execute" + +New-PSUAccessControl -Role "Team-Linux" -Tag "Team-Linux_Execute" -Type "View, Execute" + +New-PSUAccessControl -Role "Team-Tier2" -Tag "Team-Tier2_Execute" -Type "View, Execute" + +New-PSUAccessControl -Role "Team-Mgmt" -Tag "Team-Mgmt_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "Team-Mgmt" -Tag "Team-Mgmt_Modify" -Type "View, Edit, Create, Delete, Execute" + +##### Apps (or specific AppNames) +<# New App Tag example +New-PSUAccessControl -Role "App-Infra-XXXXX" -Tag "Infra-XXXXX_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "App-Infra-XXXXX" -Tag "Infra-XXXXX_Modify" -Type "View, Edit, Create, Delete, Execute" +#> +New-PSUAccessControl -Role "App-Infra-VMware" -Tag "Infra-VMware_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "App-Infra-VMware" -Tag "Infra-VMware_Modify" -Type "View, Edit, Create, Delete, Execute" + +New-PSUAccessControl -Role "App-ITD-WindowsServer" -Tag "ITD-WindowsServer_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "App-ITD-WindowsServer" -Tag "ITD-WindowsServer_Modify" -Type "View, Edit, Create, Delete, Execute" + +New-PSUAccessControl -Role "App-Shared-PowerSchool" -Tag "Shared-PowerSchool_Execute" -Type "View, Execute" +New-PSUAccessControl -Role "App-Shared-PowerSchool" -Tag "Shared-PowerSchool_Modify" -Type "View, Edit, Create, Delete, Execute" + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak new file mode 100644 index 0000000..1fbba74 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak @@ -0,0 +1,14 @@ +Set-PSUAuthenticationMethod -Type "Form" -ScriptBlock { +param( + [PSCredential]$Credential +) + +# +# You can call whatever cmdlets you like to conduct authentication here. +# Just make sure to return the $Result with the Success property set to $true +# + +New-PSUAuthenticationResult -ErrorMessage 'Bad username or password' +} +Set-PSUAuthenticationMethod -Type "Windows" +Set-PSUAuthenticationMethod -Type "Saml2" -Disabled \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak20240802 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak20240802 new file mode 100644 index 0000000..b3c9a77 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.bak20240802 @@ -0,0 +1,87 @@ +Set-PSUAuthenticationMethod -Type "Form" -ScriptBlock { +param( + [PSCredential]$Credential + ) + + Add-Type -AssemblyName System.DirectoryServices.AccountManagement + + # is this a UPN? + if ( $Credential.UserName.IndexOf('@') -gt -1 ) { + + # juggle back and forth from SID to get NTAccount format + $NTAccountName = ([System.Security.Principal.NTAccount]$Credential.UserName).Translate([System.Security.Principal.SecurityIdentifier]).Translate([System.Security.Principal.NTAccount]).Value + + } elseif ( $Credential.UserName.IndexOf('\') -gt -1 ) { + + # already NTAccount format + $NTAccountName = $Credential.UserName + + } else { + + # someone didn't enter their domain... + $NTAccountName = "NDGOV\" + $Credential.GetNetworkCredential().UserName + + } + + # split domain and username + $DomainName, $UserName = $NTAccountName.Split('\',2) + + # perform auth with AD + $PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( 'Domain', $DomainName ) + $Authenticated = $PrincipalContext.ValidateCredentials( $UserName, $Credential.GetNetworkCredential().Password, 'Negotiate, Sealing' ) + + if ( $Authenticated ) { + + # discover the user principal, needed for the user DN + $UserPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $NTAccountName ) + + # get the user's domain + #$UserDomainContext = [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new( 'Domain', $DomainName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) + #$UserDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain( $UserDomainContext ) + + # get the computer's domain + #$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() + + # hold all the user groups + [System.Collections.Generic.List[hashtable]]$Groups = @() + + # get groups from user's domain + [adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName)))", @('name') ).FindAll().ForEach({ + + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $UserDomain.Name + }) + + }) + <# + # get groups from the computer's domain (if different) + if ( $UserDomain.Name -ne $ComputerDomain.Name ) { + + # lookup the user's foreign security principal in the computer's domain + $ForeignSecurityPrincipal = [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=foreignSecurityPrincipal)(objectClass=foreignSecurityPrincipal)(name=$($UserPrincipal.Sid)))", @('distinguishedName') ).FindOne().Properties['distinguishedName'][0] + + # find all the group memberships + [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$ForeignSecurityPrincipal))", @('name') ).FindAll().ForEach({ + + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $ComputerDomain.Name + }) + + }) + + } + #> + New-PSUAuthenticationResult -Success -UserName $UserPrincipal.UserPrincipalName -Claims { + $Groups | ForEach-Object { New-PSUAuthorizationClaim @_ } + } + + } else { + + New-PSUAuthenticationResult -ErrorMessage 'Bad username or password :)' + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.ps1 new file mode 100644 index 0000000..7f3048e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/authentication.ps1 @@ -0,0 +1,86 @@ +Set-PSUAuthenticationMethod -Type "Form" -ScriptBlock { +param( + [PSCredential]$Credential + ) + + Add-Type -AssemblyName System.DirectoryServices.AccountManagement + + # is this a UPN? + if ( $Credential.UserName.IndexOf('@') -gt -1 ) { + + # juggle back and forth from SID to get NTAccount format + $NTAccountName = ([System.Security.Principal.NTAccount]$Credential.UserName).Translate([System.Security.Principal.SecurityIdentifier]).Translate([System.Security.Principal.NTAccount]).Value + + } elseif ( $Credential.UserName.IndexOf('\') -gt -1 ) { + + # already NTAccount format + $NTAccountName = $Credential.UserName + + } else { + + # someone didn't enter their domain... + $NTAccountName = "NDGOV\" + $Credential.GetNetworkCredential().UserName + + } + + # split domain and username + $DomainName, $UserName = $NTAccountName.Split('\',2) + + # perform auth with AD + $PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( 'Domain', $DomainName ) + $Authenticated = $PrincipalContext.ValidateCredentials( $UserName, $Credential.GetNetworkCredential().Password, 'Negotiate, Sealing' ) + + if ( $Authenticated ) { + + # discover the user principal, needed for the user DN + $UserPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $NTAccountName ) + + # get the user's domain + $UserDomainContext = [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new( 'Domain', $DomainName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) + $UserDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain( $UserDomainContext ) + + # get the computer's domain + #$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() + + # hold all the user groups + [System.Collections.Generic.List[hashtable]]$Groups = @() + + # get groups from user's domain + #[adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName)))", @('name') ).FindAll().ForEach({ + [adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName))(name=ITD-PSUniversal-*))", @('name') ).FindAll().ForEach({ + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $UserDomain.Name + }) + }) + <# + # get groups from the computer's domain (if different) + if ( $UserDomain.Name -ne $ComputerDomain.Name ) { + + # lookup the user's foreign security principal in the computer's domain + $ForeignSecurityPrincipal = [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=foreignSecurityPrincipal)(objectClass=foreignSecurityPrincipal)(name=$($UserPrincipal.Sid)))", @('distinguishedName') ).FindOne().Properties['distinguishedName'][0] + + # find all the group memberships + [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$ForeignSecurityPrincipal))", @('name') ).FindAll().ForEach({ + + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $ComputerDomain.Name + }) + + }) + + } + #> + New-PSUAuthenticationResult -Success -UserName $UserPrincipal.UserPrincipalName -Claims { + $Groups | ForEach-Object { New-PSUAuthorizationClaim @_ } + } + + } else { + + New-PSUAuthenticationResult -ErrorMessage 'Bad username or password :)' + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/dashboards.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/dashboards.ps1 new file mode 100644 index 0000000..3672bda --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/dashboards.ps1 @@ -0,0 +1,6 @@ +New-PSUApp -Name "PSUVariableReview" -FilePath "dashboards\PSUVariableReview\PSUVariableReview.ps1" -BaseUrl "/PSUVariableReview" -Authenticated -AutoDeploy +New-PSUApp -Name "Infra-VMware_Snapshot" -FilePath "dashboards\Infra-VMware_Snapshot\Infra-VMware_Snapshot.ps1" -BaseUrl "/Infra-VMware_Snapshot" -Authenticated -AutoDeploy +New-PSUApp -Name "ServiceNowDumps" -FilePath "dashboards\ServiceNowDumps\ServiceNowDumps.ps1" -BaseUrl "/ServiceNowDumps" -Authenticated -AutoDeploy +New-PSUApp -Name "NewITDADServiceAccount" -FilePath "dashboards\NewITDADServiceAccount\NewITDADServiceAccount.ps1" -BaseUrl "/NewITDADServiceAccount" -Authenticated -AutoDeploy +New-PSUApp -Name "ITD-WindowsServer_FileManagement" -FilePath "dashboards\ITD-WindowsServer_FileManagement\ITD-WindowsServer_FileManagement.ps1" -BaseUrl "/ITD-WindowsServer_FileManagement" -Authenticated -AutoDeploy +New-PSUApp -Name "ServiceNow" -FilePath "dashboards\ServiceNow\ServiceNow.ps1" -BaseUrl "/ServiceNow" -Authenticated -AutoDeploy \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/endpoints.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/endpoints.ps1 new file mode 100644 index 0000000..a756b72 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/endpoints.ps1 @@ -0,0 +1,107 @@ +New-PSUEndpoint -Url "/Get-ITDService" -Method @('GET') -Endpoint { + # Enter your script to process requests. + $GetServiceParams = @{} + If ($Name) { + #$GetServiceParams.Name = $Name + } + Else { + # Write-Error "Please add query string to Url" # moar notes + } + + If ($ComputerName) { + $ComputerName = $ComputerName -split ',' + } + Else { + $ComputerName = $env:COMPUTERNAME + } + + $Services = Invoke-Command -ComputerName $ComputerName -ArgumentList $Name -ScriptBlock { + $GetServiceParams = @{ + Name = $args[0] + } + Get-Service @GetServiceParams -ErrorAction SilentlyContinue + } + + Write-Output ($Services | select pscomputername, name, displayname, status, servicetype, @{n = 'DependentServicesName'; e = { $_.servicesdependedon.name } }) + } + New-PSUEndpoint -Url "/Get-ITDADUser" -Method @('GET') -Endpoint { + #If($Identity){ + # Get-ADUser -Identity $Identity -Properties LockedOut,MemberOf + # } + + + + Invoke-PSUScript -Script 'Get-ITDADUser_script.ps1' -Identity $Identity -Wait + } -Authentication -Role @('ITD-PSUniversal-API-Execute') + New-PSUEndpoint -Url "/Get-ITDADGroup" -Method @('GET') -Endpoint { + If ($Identity) { + Get-ADGroup -Identity $Identity + } + } + New-PSUEndpoint -Url "/Get-ITDADGroupMember" -Method @('GET') -Endpoint { + # test notes + If ($Identity) { + Get-ADGroupMember -Identity $Identity | select SamAccountName, Name, DistinguishedName + } + } + New-PSUEndpoint -Url "/New-ITDVMwareVMSnapshot" -Method @('POST') -Endpoint { + $User = ConvertFrom-Json $Body + #New-User $User + Write-Output $User + } + New-PSUEndpoint -Url "/zm" -Method @('GET') -Endpoint { + $env:username + + Connect-ITDvCenter + Get-Datacenter + Disconnect-VIServer -Server * -Confirm:$false + } + New-PSUEndpoint -Url "/Get-ITDVMwareVM" -Method @('GET') -Endpoint { + # Enter your script to process requests. + Connect-ITDvCenter + + $Names = $Name -split ',' + $Result = [System.Collections.ArrayList]@() + + $LoopOutput = ForEach ($n in $Names) { + $VM = Get-VM -Name $n + $VMDisks = $VM | Get-HardDisk + $obj = [PSCustomObject]@{ + Name = $VM.Name; + PowerState = $VM.PowerState; + NumCpu = $VM.NumCpu; + MemoryGB = $VM.MemoryGB; + ProvisionedSpaceGB = ($VMDisks | Measure-Object -Sum CapacityGB).Sum + } + $null = $Result.Add($obj) + } + #> + + Disconnect-VIServer -Server * -Confirm:$false | Out-Null + + Write-Output $Result + } + New-PSUEndpoint -Url "/SyncVMwareVMtoSharePointAPI" -Method @('GET') -Endpoint { + # Enter your script to process requests. + Connect-ITDvCenter + + If ($Name) { + $VM = Get-VM -Name $Name + $VMDisks = $VM | Get-HardDisk + $obj = [PSCustomObject]@{ + Name = $VM.Name; + PowerState = $VM.PowerState; + NumCpu = $VM.NumCpu; + MemoryGB = $VM.MemoryGB; + ProvisionedSpaceGB = ($VMDisks | Measure-Object -Sum CapacityGB).Sum + } + + Write-Output "VMware:" + Write-Output $obj + + Sync-ITDVMwareVMMetadataToSharePoint -ComputerName $Name + } + #> + + Disconnect-VIServer -Server * -Confirm:$false | Out-Null + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/environments.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/environments.ps1 new file mode 100644 index 0000000..98a13c9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/environments.ps1 @@ -0,0 +1,5 @@ +New-PSUEnvironment -Name "7.2.19" -Version "7.2.19" -Path "C:\Program Files\PowerShell\7\pwsh.exe" -Variables @('*') -Description "PowerShell environment for version 7.2.19. This was automatically detected on the server." +New-PSUEnvironment -Name "Windows PowerShell 5.1" -Version "5.1.20348.2582" -Path "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Variables @('*') -Description "PowerShell environment for version 5.1.20348.2582. This was automatically detected on the server." +New-PSUEnvironment -Name "Integrated" -Version "7.3.7" -Path "Universal.Server" -Variables @('*') -Description "An environment for running scripts directly in the PowerShell Universal server." +New-PSUEnvironment -Name "Agent" -Version "7.3.7" -Path "Universal.Agent" -Variables @('*') -Description "An environment for running scripts in an external PowerShell Universal agent process." +New-PSUEnvironment -Name "PowerShell 7" -Version "7.2.19" -Path "pwsh" -Variables @('*') -Description "The current version of PowerShell 7." \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/loginPage.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/loginPage.ps1 new file mode 100644 index 0000000..682058d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/loginPage.ps1 @@ -0,0 +1,15 @@ +$Parameters = @{ + Image = "/PSUniversal_Extras/logo.png" + Title = "PowerShell Universal" + Links = @( + New-PSULoginPageLink -Text 'ServiceNow' -Url 'https://northdakota.service-now.com/' + New-PSULoginPageLink -Text 'VMware vCenter' -Url 'https://itdvmvc1.nd.gov/ui' + New-PSULoginPageLink -Text 'Microsoft Azure' -Url 'https://portal.azure.com' + New-PSULoginPageLink -Text 'Passwordstate' -Url 'https://itdpv.nd.gov' + New-PSULoginPageLink -Text 'Solarwinds' -Url 'https://solarwinds.nd.gov/' + New-PSULoginPageLink -Text 'Panorama' -Url 'https://panorama-gov.nd.gov/php/login.php' + New-PSULoginPageLink -Text 'Ansible' -Url 'https://ansible.nd.gov/#/login' + New-PSULoginPageLink -Text 'Confluence Wiki' -Url 'https://wiki.nd.gov/i/dashboard.action' + ) +} +New-PSULoginPage @Parameters \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/publishedFolders.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/publishedFolders.ps1 new file mode 100644 index 0000000..106a53b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/publishedFolders.ps1 @@ -0,0 +1 @@ +New-PSUPublishedFolder -RequestPath "/PSUniversal_Extras" -Path "E:\PSUniversal_Extras" -Name "PSUniversal_Extras" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/roles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/roles.ps1 new file mode 100644 index 0000000..d7af9b4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/roles.ps1 @@ -0,0 +1,160 @@ +New-PSURole -Name "Administrator" -Description "Administrators can manage settings, create and edit any entity and view all the entities with PowerShell Universal." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + #$false + + <# + $UserName = ($User.Identity.Name) + $UserName = $UserName.Substring($UserName.IndexOf('\') + 1, ($UserName.Length - ($UserName.IndexOf('\') + 1))) + + $IsMember = $false; + + # Perform LDAP Group Member Lookup + $Searcher = New-Object DirectoryServices.DirectorySearcher + $Searcher.SearchRoot = 'LDAP://OU=USERS, OU=ITD, DC=nd, DC=gov' # INSERT ROOT LDAP HERE + $Searcher.Filter = "(&(objectCategory=person)(memberOf=CN=ITD-PSUniversal-Admin,OU=ITDGROUPS,OU=GROUPS,OU=ITD,DC=nd,DC=gov))" #GROUP INSERT DN TO CHECK HERE + $Users = $Searcher.FindAll() + $Users | ForEach-Object { + If ($_.Properties.samaccountname -eq $UserName) { + $IsMember = $true; + "$UserName is a member of admin group!" | Out-File "C:\test\adgroup.txt" + } + else { + "$UserName is NOT member of admin group!" | Out-File "C:\test\adgroup.txt" + } + } + + return $IsMember + #> + + param($User) + + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains 'ITD-PSUniversal-Admin' + } + New-PSURole -Name "Operator" -Description "Operators have access to manage and execute scripts, create other entities within PowerShell Universal but cannot manage PowerShell Universal itself." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + $false + } + New-PSURole -Name "Reader" -Description "Readers have read-only access to PowerShell Universal. They cannot make changes to any entity within the system." -Policy { + param( + [Security.ClaimsPrincipal] + $User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + $User | ConvertTo-Json | Set-Content ("C:\temp\user-" + $User.Identity.Name + ".json") + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -match "ITD-PSUniversal-*" + + } + New-PSURole -Name "Execute" -Description "Execute scripts within PowerShell Universal." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + $false + } + New-PSURole -Name "User" -Description "Does not have access to the admin console but can be assigned resources like APIs, scripts, dashboards and pages." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. + #> + + $false + } + + + ###### Team-TeamName nd.gov Active Directory groups + New-PSURole -Name "Team-Windows" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Windows" + } + + New-PSURole -Name "Team-Linux" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Linux" + } + + New-PSURole -Name "Team-ConnectND" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-ConnectND" + } + + New-PSURole -Name "Team-Network" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Network" + } + + New-PSURole -Name "Team-Tier2" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Tier2" + } + + New-PSURole -Name "Team-Mgmt" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Mgmt" + } + + + ###### ITD App-AppName nd.gov Active Directory Groups + <# New Role for Apps example + New-PSURole -Name "App-Infra-XXXXX" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Infra-XXXXX" + } + #> + + New-PSURole -Name "App-Infra-VMware" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Infra-VMware" + } + + New-PSURole -Name "App-ITD-WindowsServer" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-ITD-WindowsServer" + } + + New-PSURole -Name "App-Shared-Powerschool" -Policy { + param($User) + $Roles = $User.Claims | Where-Object Type -eq Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-App-Shared-PowerSchool" + } + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/schedules.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/schedules.ps1 new file mode 100644 index 0000000..9269e4d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/schedules.ps1 @@ -0,0 +1,13 @@ +New-PSUSchedule -Cron "0 13 * * 1-5" -Script "Infra-VMware.VirtualMachine\Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -TimeZone "America/Chicago" -Parameters @{ + NewBuilds = $true +} -Name "Move-ITDVMwareVMToAppNameFolder_Auto" +New-PSUSchedule -Cron "7/30 8-16 * * *" -Script "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Auto.ps1" -TimeZone "America/Chicago" -Name "New-ITDWindowsVm_Auto" -Paused +New-PSUSchedule -Cron "0 * * * *" -Script "Infra-VMware.Snapshot\Remove-ITDVMwareVMSnapshotExpired.ps1" -TimeZone "America/Chicago" -Name "Remove-ITDVMwareVMSnapshotExpired" -Paused -RandomDelay +New-PSUSchedule -Cron "27 8-16/2 * * 1-5" -Script "ITD-WindowsServer.General\Remove-ITDWindowsServer.ps1" -TimeZone "America/Chicago" -Name "Remove-ITDWindowsServer" -Paused -RandomDelay -RandomDelayMaximum 300 +New-PSUSchedule -Cron "33 8-16/2 * * *" -Script "Infra-VMware.VirtualMachine\Set-ITDVMwareVMTagFromCmdb.ps1" -TimeZone "America/Chicago" -Name "Set-ITDVMwareVMTagFromCmdb_NewBuilds" -Paused +New-PSUSchedule -Cron "0 */1 * * *" -Script "Infra-VMware.VirtualMachine\Sync-ITDServerBuildRITMs.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDServerBuildRITMs.ps1" -Paused -RandomDelay -RandomDelayMaximum 600 +New-PSUSchedule -Cron "23 8-16/2 * * *" -Script "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMTagsFromCmdb.ps1" -TimeZone "America/Chicago" -Name "Sync-ITDVMwareVMTagsFromCmdb" -Paused +New-PSUSchedule -Cron "13 8-17 * * *" -Script "Infra-Servers-PowerShellUniversal\Update-ITDModule.ps1" -TimeZone "America/Chicago" -Name "Update-ITDModule.ps1" -Paused -RandomDelay -RandomDelayMaximum 600 +New-PSUSchedule -Cron "*/20 * * * *" -Script "Infra-VMware.VirtualMachine\Update-ITDSnowVMTaskDescription.ps1" -TimeZone "America/Chicago" -Name "Update-ITDSnowVMTaskDescription" -Paused -RandomDelay +New-PSUSchedule -Cron "*/20 * * * *" -Script "Infra-VMware.Snapshot\Update-ITDVMwareVMSnapshotStatus.ps1" -TimeZone "America/Chicago" -Name "Update-ITDVMwareVMSnapshotStatus" -Paused -RandomDelay +New-PSUSchedule -Cron "* * * * *" -Script "ZM-Test\Test-ITDSchedule.ps1" -TimeZone "America/Chicago" -Credential "ndgov_svcitdvmvcauto" -Environment "Agent" -Name "ZM-Test\Test-ITDSchedule" -Paused \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/scripts.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/scripts.ps1 new file mode 100644 index 0000000..ed6e9ee --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/scripts.ps1 @@ -0,0 +1,39 @@ +New-PSUScript -Name "Add-ITDADUserSPN.ps1" -Description "Add-ITDADUserSPN.ps1" -Tag @('ITD-WindowsServer_Modify','Team-Windows_Execute') -Path "Infra-ActiveDirectory.Object\Add-ITDADUserSPN.ps1" -Environment "Agent" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuad" +New-PSUScript -Name "Add-ITDServerBuildRitmToSql.ps1" -Description "Add-ITDServerBuildRitmToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Add-ITDServerBuildRitmToSql.ps1" -Environment "Agent" +New-PSUScript -Name "Add-ITDSolarwindsNode.ps1" -Description "Add-ITDSolarwindsNode.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Add-ITDSolarwindsNode.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Approve-ITDWindowsServer.ps1" -Description "Approve-ITDWindowsServer.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\Approve-ITDWindowsServer.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Get-HelloWorld.ps1" -Description "Get-HelloWorld.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ZM-Test\Get-HelloWorld.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Get-ITDExpiredFiles.ps1" -Description "Get-ITDExpiredFiles.ps1" -Tag @('ITD-WindowsServer_Modify','Team-Windows_Execute') -Path "ITD-WindowsServer.FileManagement\Get-ITDExpiredFiles.ps1" -Environment "PowerShell 7" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuwin" +New-PSUScript -Name "Get-ITDVMwareLunIdNextAvailable.ps1" -Description "Get-ITDVMwareLunIdNextAvailable.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Get-ITDVMwareLunIdNextAvailable.ps1" +New-PSUScript -Name "Get-ITDVMwareVMGuestIPsForPA.ps1" -Description "Get-ITDVMwareVMGuestIPsForPA.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Get-ITDVMwareVMGuestIPsForPA.ps1" +New-PSUScript -Name "Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Description "Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Move-ITDVMwareVMToAppNameFolder_Auto.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "New-ITDADServiceAccount.ps1" -Description "New-ITDADServiceAccount.ps1" -Tag @('ITD-WindowsServer_Modify','Team-Windows_Execute') -Path "Infra-ActiveDirectory.Object\New-ITDADServiceAccount.ps1" -Environment "Agent" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuad" +New-PSUScript -Name "New-ITDPSUScript.ps1" -Description "New-ITDPSUScript.ps1" -Tag @('ITD-WindowsServer_Modify','Team-Windows_Execute') -Path "Infra-Servers-PowerShellUniversal\New-ITDPSUScript.ps1" -Environment "Integrated" +New-PSUScript -Name "New-ITDVMwareSharePointVMRecordFromRITM.ps1" -Description "New-ITDVMwareSharePointVMRecordFromRITM.ps1 [[-Fqdn] ] [[-RitmNum] ]" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\New-ITDVMwareSharePointVMRecordFromRITM.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaassprw" +New-PSUScript -Name "New-ITDVMwareVMSnapshotTask.ps1" -Description "New-ITDVMwareVMSnapshotTask.ps1" -Tag @('Infra-VMware_Modify','Team-Linux_Execute','Team-Network_Execute','Team-Tier2_Execute','Team-Windows_Execute') -Path "Infra-VMware.Snapshot\New-ITDVMwareVMSnapshotTask.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" -Role @('Team-Windows') +New-PSUScript -Name "New-ITDWindowsVm_Auto.ps1" -Description "New-ITDWindowsVm_Auto.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Auto.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVm_Step3.ps1" -Description "New-ITDWindowsVm_Step3.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVm_Step3.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Manual.ps1" -Description "New-ITDWindowsVmAzure_Manual.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\New-ITDWindowsVmAzure_Manual.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Step1.ps1" -Description "New-ITDWindowsVmAzure_Step1.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmAzure_Step1.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmAzure_Step2.ps1" -Description "New-ITDWindowsVmAzure_Step2.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmAzure_Step2.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmVMware_Manual.ps1" -Description "New-ITDWindowsVmVMware_Manual.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\New-ITDWindowsVmVMware_Manual.ps1" -Environment "Agent" -DisableManualInvocation -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmVMware_Step1.ps1" -Description "New-ITDWindowsVmVMware_Step1.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmVMware_Step1.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-ITDWindowsVmVMware_Step2.ps1" -Description "New-ITDWindowsVmVMware_Step2.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.Lifecycle\New-ITDWindowsVmVMware_Step2.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "New-TestNestedInvoke.ps1" -Description "New-TestNestedInvoke.ps1" -Tag @('Team-Windows_Modify') -Path "ZM-Test\New-TestNestedInvoke.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Remove-ITDExpiredFiles.ps1" -Description "Remove-ITDExpiredFiles.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.FileManagement\Remove-ITDExpiredFiles.ps1" -Environment "PowerShell 7" -ErrorAction "Stop" -Credential "ndgov_svcitdpsuwin" +New-PSUScript -Name "Remove-ITDSolarwindsNode.ps1" -Description "Remove-ITDSolarwindsNode.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Remove-ITDSolarwindsNode.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Remove-ITDVMwareVMSnapshotExpired.ps1" -Description "Remove-ITDVMwareVMSnapshotExpired.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Snapshot\Remove-ITDVMwareVMSnapshotExpired.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" +New-PSUScript -Name "Remove-ITDWindowsServer.ps1" -Description "Remove-ITDWindowsServer.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "ITD-WindowsServer.General\Remove-ITDWindowsServer.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Set-ITDVMwareVMTagFromCmdb.ps1" -Description "Set-ITDVMwareVMTagFromCmdb.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Set-ITDVMwareVMTagFromCmdb.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "Sync-ITDServerBuildRITMs.ps1" -Description "Sync-ITDServerBuildRITMs.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Sync-ITDServerBuildRITMs.ps1" -Environment "Agent" +New-PSUScript -Name "Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Description "Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Tag @('Infra-VMware_Modify','Team-Mgmt_Execute') -Path "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMMetadataToSharePoint.ps1" -Environment "Agent" -Credential "ndgov_svcitdiaassprw" +New-PSUScript -Name "Sync-ITDVMwareVMTagsFromCmdb.ps1" -Description "Sync-ITDVMwareVMTagsFromCmdb.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Sync-ITDVMwareVMTagsFromCmdb.ps1" -Environment "Agent" -Credential "ndgov_svcitdvmvcauto" +New-PSUScript -Name "Sync-ITDVMwareVMToSql.ps1" -Description "Sync-ITDVMwareVMToSql.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Administration\Sync-ITDVMwareVMToSql.ps1" -Environment "PowerShell 7" -Credential "ndgov_itdvcenterscript" +New-PSUScript -Name "Test-InvokeZM.ps1" -Description "Test-InvokeZM.ps1" -Path "ZM-Test\Test-InvokeZM.ps1" +New-PSUScript -Name "Test-ITDSchedule.ps1" -Description "Test-ITDSchedule.ps1" -Tag @('Infra-VMware_Modify') -Path "ZM-Test\Test-ITDSchedule.ps1" +New-PSUScript -Name "Test-PSUVariable.ps1" -Description "Test-PSUVariable.ps1" -Tag @('Infra-VMware_Execute') -Path "ZM-Test\Test-PSUVariable.ps1" +New-PSUScript -Name "test-sql.ps1" -Description "test-sql.ps1" -Path "ZM-Test\test-sql.ps1" +New-PSUScript -Name "Update-ITDModule.ps1" -Description "Update-ITDModule.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-Servers-PowerShellUniversal\Update-ITDModule.ps1" -Environment "7.2.24" +New-PSUScript -Name "Update-ITDSnowVMTaskDescription.ps1" -Description "Update-ITDSnowVMTaskDescription.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.VirtualMachine\Update-ITDSnowVMTaskDescription.ps1" -Environment "Agent" -ErrorAction "Stop" +New-PSUScript -Name "Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Description "Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Tag @('ITD-WindowsServer_Modify') -Path "Infra-Monitoring-Solarwinds\Update-ITDSolarwindsNodeFromSNowRitm.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdiaasauto" +New-PSUScript -Name "Update-ITDVMwareVMSnapshotStatus.ps1" -Description "Update-ITDVMwareVMSnapshotStatus.ps1" -Tag @('Infra-VMware_Modify') -Path "Infra-VMware.Snapshot\Update-ITDVMwareVMSnapshotStatus.ps1" -Environment "PowerShell 7" -Credential "ndgov_svcitdvmsnapmgr" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/settings.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/settings.ps1 new file mode 100644 index 0000000..8c4c2a2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/settings.ps1 @@ -0,0 +1,6 @@ +$Parameters = @{ + LogLevel = "Error" + HideRunAs = $true + HideRunOn = $true +} +Set-PSUSetting @Parameters \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/tags.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/tags.ps1 new file mode 100644 index 0000000..825c974 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/tags.ps1 @@ -0,0 +1,16 @@ +New-PSUTag -Name "Infra-VMware_Execute" -Color "#d4380d" +New-PSUTag -Name "Team-Windows_Execute" -Color "#391085" +New-PSUTag -Name "Team-Network_Execute" -Color "#c41d7f" +New-PSUTag -Name "Infra-VMware_Modify" -Color "#fa541c" +New-PSUTag -Name "Team-Windows_Modify" -Color "#722ed1" +New-PSUTag -Name "Team-Network_Modify" -Color "#f759ab" +New-PSUTag -Name "Team-Linux_Execute" -Color "#096dd9" +New-PSUTag -Name "Team-Linux_Modify" -Color "#40a9ff" +New-PSUTag -Name "Team-Tier2_Execute" -Color "#389e0d" +New-PSUTag -Name "Team-Tier2_Modify" -Color "#7cb305" +New-PSUTag -Name "Shared-PowerSchool_Execute" +New-PSUTag -Name "Shared-PowerSchool_Modify" +New-PSUTag -Name "ITD-WindowsServer_Execute" -Color "#874d00" +New-PSUTag -Name "ITD-WindowsServer_Modify" -Color "#d48806" +New-PSUTag -Name "Team-Mgmt_Execute" -Color "#780650" +New-PSUTag -Name "Team-Mgmt_Modify" -Color "#c41d7f" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/triggers.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/triggers.ps1 new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/triggers.ps1 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/variables.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/variables.ps1 new file mode 100644 index 0000000..ca37175 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/.universal/variables.ps1 @@ -0,0 +1,12 @@ +New-PSUVariable -Name "sql_itdpsu1" -Vault "Database" -Type "PSCredential" +New-PSUVariable -Name "ndgov_svcitdvmsnapmgr" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdvmvcauto" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" -Role @('App-Infra-VMware') +New-PSUVariable -Name "ndgov_svcitdpsuad" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('Team-Windows','Team-Tier2') +New-PSUVariable -Name "snow_vmcred" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdiaasauto" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer','Administrator') +New-PSUVariable -Name "ndgov_itdsccmsrvcpia" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer') +New-PSUVariable -Name "ndgov_svcitdpsuwin" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-WindowsServer" -Role @('App-ITD-WindowsServer') +New-PSUVariable -Name "ndgov_svcitdvmvcro" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_svcitdiaassprw" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" +New-PSUVariable -Name "ndgov_itdvcenterscript" -Vault "Database" -Type "PSCredential" -Description "Owner: Infra-VMware" -Role @('App-Infra-VMware') +New-PSUVariable -Name "azure_iaasserviceprincipal" -Vault "Database" -Type "System.String" -Description "Owner: App-ITD-WindowsServer" -Role @('App-ITD-WindowsServer') \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Get-ITDPSUAppNameTag.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Get-ITDPSUAppNameTag.ps1 new file mode 100644 index 0000000..233f9da --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Get-ITDPSUAppNameTag.ps1 @@ -0,0 +1,21 @@ +[CmdletBinding()] +param ( + [string] + $AppName +) + +begin { + +} + +process { + switch ($AppName) { + 'Infra-VMware' { + return + } + } +} + +end { + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUScript.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUScript.ps1 new file mode 100644 index 0000000..892f195 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUScript.ps1 @@ -0,0 +1,26 @@ +Param( + [string] + $Name, + + [ValidateSet( + 'Infra-ActiveDirectory.Object', + 'Infra-VMware.Snapshot', + 'ITD-WindowsServer.General', + 'Shared-Powerschool' + )] + [string] + $Path +) + +switch ($Path){ + <# example switch condition and actions + { $_ -like "App-XXXXX"} {$TagNamesEnforced = @('Shared-XXXXX_Modify)} + #> + { $_ -eq "Infra-ActiveDirectory.Object" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Infra-VMware*" } { $TagNamesEnforced = @('Infra-VMware_Modify') } + { $_ -like "ITD-WindowsServer*" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Shared-PowerSchool*" } { $TagNamesEnforced = @('Shared-PowerSchool_Modify') } + +} +New-PSUScript -Name $Name -Path "$Path\$Name" -Tag @($TagNamesEnforced) -ScriptBlock {#code goes here +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUVariable.ps1 new file mode 100644 index 0000000..39cd15a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/New-ITDPSUVariable.ps1 @@ -0,0 +1,15 @@ +Param ( + [string] + $Name, + + [Parameter(ParameterSetName="PSCredential")] + [ValidateSet("Secret","Simple")] + [string] + $Type, + + [string[]] + $Role +) + + + New-PSUVariable -Name $Name -Type $Type -Database -Role $Role diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDADUserDescription.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDADUserDescription.ps1 new file mode 100644 index 0000000..80a17d5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDADUserDescription.ps1 @@ -0,0 +1,3 @@ +# It all starts with a single line of powershell code. +Write-Verbose ($Secret:svcitdiaasauto_test.username) -Verbose +Get-ADUser -Identity svcitddomainjoin | Set-ADUser -Description (Get-Date) -Credential $Secret:svcitdiaasauto_test \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDPSUScriptPermission.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDPSUScriptPermission.ps1 new file mode 100644 index 0000000..50e09c4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal.Administration/Set-ITDPSUScriptPermission.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +Param( + [string]$ScriptName +) + +$AllPSUScripts = Get-PSUScript +If ($ScriptName){ + $AllPSUScripts = $AllPSUScripts | Where-Object Name -eq $ScriptName +} +$Folders = $AllPSUScripts | Group-Object Folder + +ForEach ($Folder in $Folders) { + Write-Verbose -Message ("Start folder " + $Folder.Name) -Verbose + $ScriptsInFolder = $null + $TagNamesEnforced = $null + $TagNamesExisting = $null + $TagNamesToAssign = $null + + switch ($Folder.Name) { + { $_ -like "Infra-VMware*" } { $TagNamesEnforced = 'VMware-Admin_Modify' } + Default { Write-Verbose -Message ("Folder " + $Folder.Name + " does not have enforced tags")} + } + + If ($TagNamesEnforced) { + $ScriptsInFolder = $AllPSUScripts | Where-Object Folder -EQ $Folder.Name + ForEach ($PSUScript in $ScriptsInFolder) { + $TagNamesExisting = $null + $TagNamesToAssign = $null + Write-Verbose -Message ("Start " + $PSUScript.Name) -Verbose + If($PSUScript.Tag.Name -notcontains $TagNamesEnforced){ + Write-Verbose -Message ($PSUScript.Name + " enforced tag missing, attempting to fix") -Verbose + $TagNamesExisting = $PSUScript.Tag.Name + #Get-PSUScript -Name $PSUScript.Name | Set-PSUScript -Tag @('VMware-Admin_Execute','Network-Engineer_Execute') #### WORKING EXAMPLE + [string[]]$TagNamesToAssign = $TagNamesEnforced + If ($TagNamesExisting){$TagNamesToAssign += $TagNamesExisting} + Get-PSUScript -Name $PSUScript.Name | Set-PSUScript -Tag $TagNamesToAssign + } + Write-Verbose -Message ("End " + $PSUScript.Name) -Verbose + } + } + Write-Verbose -Message "End $Folder" -Verbose +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-ITDModules.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-ITDModules.ps1 new file mode 100644 index 0000000..c2df623 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-ITDModules.ps1 @@ -0,0 +1,4 @@ +# It all starts with a single line of powershell code. +$ITDModules = Get-Module -Name ITD* -ListAvailable + +Write-Output $ITDModules \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-Service.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-Service.ps1 new file mode 100644 index 0000000..54951eb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-Service.ps1 @@ -0,0 +1,2 @@ +# It all starts with a single line of powershell code. +Get-Service -ErrorAction SilentlyContinue \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-UAJobVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-UAJobVariable.ps1 new file mode 100644 index 0000000..7f292be --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Get-UAJobVariable.ps1 @@ -0,0 +1,21 @@ +Write-Verbose "UAJob" -Verbose +$UAJob + +Write-Verbose "UAJobId" -Verbose +$UAJobId + +Write-Verbose "UAScript" -Verbose +$UAScript + +Write-Verbose "UAScriptId" -Verbose +$UAScriptId + +Write-Verbose "UASchedule" -Verbose +$UASchedule + +Write-Verbose "UAScheduleId" -Verbose +$UAScheduleId + +Write-Verbose "AccessToken" -Verbose +$AccessToken + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUCredentials.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUCredentials.ps1 new file mode 100644 index 0000000..4ae1e16 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUCredentials.ps1 @@ -0,0 +1,6 @@ +# It all starts with a single line of powershell code. +$Secret:svcitdiaasauto +$Secret:testuser01 +$Secret:SNowVMCred +$Secret:AzureVMServicePrincipal +$Secret:svcitdvmvcauto \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUPlatformVariables.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUPlatformVariables.ps1 new file mode 100644 index 0000000..6de5ab9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-PSUPlatformVariables.ps1 @@ -0,0 +1,7 @@ +# It all starts with a single line of powershell code. +$Secret:itdpsu1 +$Secret:norolecred +$Secret:vmcred +$Secret:wincred +$Secret:svcitdvmsnapmgr +$Sercet:svcitdiaasauto_test \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-SQLThings.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-SQLThings.ps1 new file mode 100644 index 0000000..ed700a9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Test-SQLThings.ps1 @@ -0,0 +1,8 @@ +# It all starts with a single line of powershell code. +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + +$SqlQuery = "INSERT INTO [Infra_VMware_VirtualMachine_VMSnapshots_NPD] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('itdscmt1.nd.gov', '2024/07/30 09:24:08', 'prvzmeier@nd.gov', 2, 'Requested', '2024/07/30 11:23:51','zmeier@nd.gov','');SELECT SCOPE_IDENTITY();" +(Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:itdpsu1 -Verbose) + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Update-ITDModules.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Update-ITDModules.ps1 new file mode 100644 index 0000000..302457e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/Update-ITDModules.ps1 @@ -0,0 +1,42 @@ +####### +Write-Verbose -Message "Determine if ITD_PwshGallery is registered" -Verbose +If(Get-PSRepository -Name ITD_PwshGallery -ErrorAction SilentlyContinue){ + Write-Verbose -Message "ITD_PwshGallery found." -Verbose +} Else { + $RegisterPSRepositoryParams = @{ + Name = 'ITD_PwshGallery'; + InstallationPolicy = 'Trusted'; + SourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + PublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptSourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptPublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + } + Register-PSRepository @RegisterPSRepositoryParams +} + +Write-Verbose -Message "Retrieve list of all available modules and versions" +$ITDModules = Find-Module -Name "ITD.*" -Repository ITD_PwshGallery + + +Write-Verbose -Message "Compare local module versions to repository versions, and update if needed" +ForEach($ITDModule in $ITDModules){ + $VersionsAvailable = $null + $MostRecentVersion = $null + $RepoVersion = $null + + $VersionsAvailable = Get-Module -Name $ITDModule.name -ListAvailable + $MostRecentVersion = $VersionsAvailable | Sort-Object Version -Descending | Select -First 1 + $RepoVersion = $ITDModule.Version + + If($null -eq $MostRecentVersion) { + Write-Verbose -Message ($ITDModule.Name + " was not found locally, installing module now.") -Verbose + Install-Module -Name $ITDModule.Name -Scope AllUsers -Repository ITD_PwshGallery + } Else { + Write-Verbose -Message ($ITDModule.Name + " was found locally, comparing versions and updating if needed..") -Verbose + Write-Host -Message ($ITDModule.Name) + Write-Host -Message ("Local version is " + $MostRecentVersion.Version) + Write-Host -Message ("The Repo version is " + $RepoVersion) + Write-Host -Message ("") + Update-Module -Name $ITDModule.Name -Scope AllUsers + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/zmtest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/zmtest.ps1 new file mode 100644 index 0000000..a18f9e1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-PowerShellUniversal/zmtest.ps1 @@ -0,0 +1,2 @@ +# It all starts with a single line of powershell code. # TEST +Get-PSUIdentity \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowRecord_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowRecord_script.ps1 new file mode 100644 index 0000000..418aab1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowRecord_script.ps1 @@ -0,0 +1,6 @@ +param ( +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred -Verbose + +Get-ITDServiceNowRecord -ItemType 'Catalog task' -Number 'SCTASK0258692' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowUser_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowUser_script.ps1 new file mode 100644 index 0000000..d76f502 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Get-ITDServiceNowUser_script.ps1 @@ -0,0 +1,22 @@ +[CmdletBinding()] +param( + [Parameter(ParameterSetName = 'Email')] + [string] + $Email, + + [Parameter(ParameterSetName = 'UserName')] + [string] + $UserName +) + +#Get-Module ITD.ServiceNow -ListAvailable | select modulebase + +New-ITDServiceNowSession -Environment Test -Credential $Secret:SNowVMCred + +Get-ITDServiceNowSession + + +switch($PSCmdlet.ParameterSetName){ + 'Email' { Get-ITDServiceNowUser -Email $Email} + 'UserName' { Get-ITDServiceNowUser -Username $UserName } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/New-ITDServiceNowChangeRequest_test.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/New-ITDServiceNowChangeRequest_test.ps1 new file mode 100644 index 0000000..4c1d32c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/New-ITDServiceNowChangeRequest_test.ps1 @@ -0,0 +1,124 @@ +$Url = "https://northdakotatest.service-now.com" +$HeaderAuth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Secret:SNowVMCred.UserName, $Secret: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" + + +$PSUJobId = 123456 +$DomainName = 'nd.gov' +$RequestedBy = 'zmeier@nd.gov' +$StartDateTime = Get-Date + +New-ITDServiceNowSession -Environment Test -Credential $Secret:SNowVMCred +Get-ITDServiceNowSession +Write-Verbose -Message "Prep variables" -Verbose + + $TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + $RequestedByUsername = 'khellman' + $Category = 'Systems Platforms - Systems' + $ShortDescription = 'test' + $Description = 'test' + $Priority = 3 + $Impact = 3 + $Justification = 'justification' + $Implementation = 'implementation' + $RiskImpactAnalysis = 'riskimpactanalysis' + $BackoutPlan = 'backoutplan' + $TestPlan = 'testplan' + $WhoIsImpacted = 'whoimpacted' + $ChangeManagerUsername = 'khellman' + $ChangeCoordinatorUsername = 'khellman' + $AssignmentGroup = 'NDIT-Computer Systems Windows' + $AssignedToUsername = 'khellman' + $StartTime = Get-Date + $EndTime = $StartTime.AddMinutes(1) + + $ChgTemplateStd = Get-ITDServiceNowChangeTemplateStandard -Name $TemplateName + $ChgTemplateStdSysId = $ChgTemplateStd.sys_id.value + Write-Warning -Message ("ChgTemplateStdSysId = " + $ChgTemplateStdSysId) + + Write-Verbose -Message "Start NewRecord" -Verbose + [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') + } + + Write-Verbose -Message "Start RequestedBy" -Verbose + If ($RequestedBy) { + $ReqBy = Get-ITDServiceNowUser -Username $RequestedBy + If (@($ReqBy).count -gt 1) { + Write-Error "Multiple requested users found, creation failed." -ErrorAction Stop + } + Else { + $NewRecord += @{requested_by = $ReqBy.sys_id } + } + } + +Write-Verbose -Message "Start AssignmentGroup" -Verbose + 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 } + } + } + +Write-Verbose -Message "Start ChgManagerName" -Verbose + $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 } + } + +Write-Verbose -Message "Start ChgCoordName" -Verbose + $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 } + } + +Write-Verbose -Message "Start AssignedTousername" -Verbose + 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 } + } + } +$Uri = ($Url + "/api/sn_chg_rest/change/standard/$ChgTemplateStdSysId") + Write-Verbose -Message "Standard CHG Template SysId = $Uri" -Verbose + $InvokeRestMethodParams = @{ + Method = 'Post'; + Uri = $Uri; + Body = $NewRecord | ConvertTo-Json; + Headers = $SnowSessionHeader + ContentType = "application/json" + } + + #Write-Output $InvokeRestMethodParams + $result = (Invoke-RestMethod @InvokeRestMethodParams).result + + Write-Output $result + #> diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Update-ITDServiceNowTaskDescription_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Update-ITDServiceNowTaskDescription_script.ps1 new file mode 100644 index 0000000..0c2808f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-ServiceNow/Update-ITDServiceNowTaskDescription_script.ps1 @@ -0,0 +1,26 @@ +[CmdletBinding()] +param ( + [string] + $SCTaskNum +) +#RitmSearch ('variables.208bd5b31b0d0dd04d8943b1b24bcb69%3DInfra.ActiveDirectory.Object') +#$RitmSearch = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter ('active%3Dtrue^variables.208bd5b31b0d0dd04d8943b1b24bcb69%3DInfra-ActiveDirectory.Object') -Verbose + +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred + +# search Generic Active Directory Service Account tasks +$SCTaskSearch = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter ('active=true^variables.208bd5b31b0d0dd04d8943b1b24bcb69=Infra-ActiveDirectory.Object') -Verbose +Write-Verbose -Message ("SCTaskSearch found: " + @($SCTaskSearch).count) -Verbose + +ForEach ($SCTask in $SCTaskSearch) { + # get ritm and look for addl comments about AD + $RitmToReview = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId $SCTask.request_item.value -IncludeCustomVariable + $task_short_description_search = 'Admin task to gather Server Information' + $StringSearchStart = "Please create a new nd.gov Active Directory service account with the following details, following guidelines found in KB0016867.*" + If ($RitmToReview.customvariable.additional_comments.value -like $StringSearchStart -and $SCTask.short_description -eq $task_short_description_search ){ + Write-Verbose -Message ($SCTask.Number + " match, update short_description") + Update-ITDServiceNowRecord -ItemType "Catalog Task" -Number $SCTask.number -Values @{ + short_description = 'Active Directory Service Account Provisioning' + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Approve-ITDWindowsServer_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Approve-ITDWindowsServer_script.ps1 new file mode 100644 index 0000000..8944045 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Approve-ITDWindowsServer_script.ps1 @@ -0,0 +1,131 @@ +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object {$_.number.value -EQ $SCTaskNum} +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number.value + Write-Verbose -Message "Start $SCTasknum" -Verbose + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + $ComputerName = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $OperatingSystem = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).operating_system + + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + $FormFQDN = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $FormHostName = $FormFQDN.split('.')[0] + + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + # Ci does not exist + Write-Verbose -Message ("Ci not found") -Verbose + } + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Other' } + } + + Write-Verbose -Message "Confirm all agents are running" + $ProcessList = @('ccmexec', 'cohesity*', 'nessus*', 'cortex*') + switch ($target_platform) { + 'VMware' { + $ProcessList += 'vmtoolsd' + } + 'Azure' { + Write-Verbose -Message "vmtoolsd not required for Azure VM" + } + Default { + Write-Verbose -Message "no Ci means no platform check" + } + } + + try { + #$Secret:itdsccmsrvcpiandgov + $RunningProcess = Invoke-Command -Credential $Secret:itdsccmsrvcpiandgov -ComputerName $FormFQDN -ArgumentList $ProcessList -ErrorAction Stop -ScriptBlock { + Get-Process + } + + If ($RunningProcess) { + ForEach ($ProcessName in $ProcessList) { + If ($RunningProcess -match $ProcessName) { + Write-Verbose -Message "Process $ProcessName found." -Verbose + } + Else { + Write-Warning -Message "Process $ProcessName not found" + $BuildComplete = $false + } + } + } + } + catch [System.Management.Automation.Remoting.PSRemotingTransportException] { + Write-Warning -Message "$FormFQDN unreachable via PSRemoting" + $BuildComplete = $false + } + + # if Task has been open for more than x hours, update description for humans to review + $Hours = 6 + If ($SCTask.opened_at.value -lt (Get-Date).AddHours(-$Hours)) { + $work_notes = ("New build Ci has not been found after $Hours hours, problem may have occurred. Please review.`nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $OperatingSystem VM Build for $ComputerName, NEED HUMAN REVIEW" + + <#Update-ServiceNowRecord -ID $SCTask.number -Values @{ + work_notes = $work_notes; + shortdescription = $shortdescription; + }#> + } + + If ($BuildComplete -ne $false) { + Write-Verbose "All required processes running, Windows is ready for use. Update SCTask to notify physical/virtual hardware stakeholders." -Verbose + $work_notes = ("$target_platform $hardware_type $FormFQDN Windows Guest OS complete. `nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $hardware_type $FormFQDN Windows Guest OS complete." + + Write-Verbose -Message "Work notes: $work_notes" -Verbose + Write-Verbose -Message "Short description: $shortdescription" -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $work_notes; + close_notes = "$FQDN $target_platform Windows Guest OS complete."; + #short_description = $shortdescription; + state = 'Closed Complete' + } + } + + Write-Verbose -Message "End $SCTasknum" -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Get-ITDExpiredFilesAuto_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Get-ITDExpiredFilesAuto_script.ps1 new file mode 100644 index 0000000..5aa8782 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Get-ITDExpiredFilesAuto_script.ps1 @@ -0,0 +1,13 @@ +Param( + [string] + $ComputerName +) + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + $GetITDExpiredFilesParams = @{ + ComputerName = $ComputerName; + } + Get-ITDExpiredFilesAuto @GetITDExpiredFilesParams -Credential $Secret:itdsccmsrvcpiandgov -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName +} Else { + Get-ITDExpiredFilesAuto -Credential $Secret:itdsccmsrvcpiandgov -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/New-ITDWindowsVmAzure_ManualExecution.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/New-ITDWindowsVmAzure_ManualExecution.ps1 new file mode 100644 index 0000000..1dde004 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/New-ITDWindowsVmAzure_ManualExecution.ps1 @@ -0,0 +1,59 @@ +[CmdletBinding()] + param ( + [string] + $ComputerName, + + [int] + $CPU = 1, + + [int] + $MemoryGB = 4, + + [int] + $DiskOsGB = 128, + + [int] + $DiskDataGB = 0, + + [string] + $Subnet, + + [string] + $OS, + + [string] + $Environment, + + [string] + $Subscription, + + [string] + $AppName, + + [string] + $LicensingRestrictions + ) + +$params = @{ + ComputerName = $ComputerName; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + Subscription = $Subscription; + AppName = $AppName; + LicensingRestrictions = $LicensingRestrictions; + Credential = $Credential; +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = 'Pqt8Q~E-dDmQugcPPWdaK2t_4retS41VVVVOZbOx' # $Secret:AzureVMServicePrincipal # $IaasAutoAzApp +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +New-ITDWindowsVmAzure @params -Credential $PrvCred -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDExpiredFilesAuto_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDExpiredFilesAuto_script.ps1 new file mode 100644 index 0000000..89b6e54 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDExpiredFilesAuto_script.ps1 @@ -0,0 +1,82 @@ +Param( + [string] + $ComputerName, + + [switch] + $WhatIf, + + [switch] + $Quiet +) + +$RemoveITDExpiredFilesAutoParams = @{ + +} + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + Write-Verbose -Message "ComputerName parameter" + $RemoveITDExpiredFilesAutoParams += @{ComputerName = $ComputerName } +} +If ($PSBoundParameters.ContainsKey('WhatIf')) { + Write-Verbose -Message "WhatIf parameter" + $RemoveITDExpiredFilesAutoParams += @{WhatIf = $true } +} + +$StartTime = (Get-Date) + +$FilesRemoved = Remove-ITDExpiredFilesAuto @RemoveITDExpiredFilesAutoParams -Verbose -Credential $Secret:itdsccmsrvcpiandgov + +# get information for notes +$DiskBytesRecovered = ($FilesRemoved | Measure-Object -Sum length).Sum +$Notes = "PSComputerName~Length~FullName" + "`n" +$Notes += ForEach ($File in $FilesRemoved) { + If ($File) { + $File.PSComputerName + "~" + $File.Length + "~" + $File.FullName + "`n" + } +} +$Notes += "$DiskBytesRecovered bytes of disk saved." +Write-Verbose -Message "Notes: `n$Notes" -Verbose + +$EndTime = (Get-Date) + +If ($PSBoundParameters.ContainsKey('Quiet') -and $Quiet -eq $true) { + Write-Verbose -Message "Quiet mode enabled. No ServiceNow interactions will be done." -Verbose +} +Else { + Write-Verbose -Message "Quiet mode disabled. ServiceNow CHG will be generated." + # create std chg and close it + New-ITDServiceNowSession Test -Credential $Secret:SNowVMCred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = 'zmeier'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "Remove files flagged for expiration and cleanup - Remove-ITDExpiredFilesAuto_script - $UAJobId"; + Description = "Remove files flagged for expiration and cleanup"; + Justification = "Some files are generated on a recurring basis causing increase in disk space usage. This automation removes specific file types from specified file paths that have been flagged for removal."; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low, files can be discovered before the removal"; + BackoutPlan = "Restore from backup (if applicable)" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartTime + EndTime = $EndTime; + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = 'zmeier'; + } + If ($PSBoundParameters.ContainsKey('WhatIf')) { + $NewITDServiceNowChangeRequestParams.ShortDescription += " -WhatIf" + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams + + Update-ITDServiceNowRecord -ItemType "Change Request" -Number $CHG.Number.Value -Values @{ + work_notes = $Notes; + } + + Complete-ITDServiceNowChangeRequest -Number $CHG.Number.value -CloseCode "Successful" -CloseNotes "Files removed." +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDSolarwindsNode_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDSolarwindsNode_script.ps1 new file mode 100644 index 0000000..22db36a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDSolarwindsNode_script.ps1 @@ -0,0 +1,10 @@ +Param( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName +) + +ForEach ($cn in $ComputerName) { + Write-Verbose -Message "Attempt Solarwinds removal for $cn" -Verbose + Remove-ITDSolarwindsNode -ComputerName $cn -Credential $Secret:svcitdiaasauto -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDWindowsServer_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDWindowsServer_script.ps1 new file mode 100644 index 0000000..c0bf8dd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-Windows.General/Remove-ITDWindowsServer_script.ps1 @@ -0,0 +1,86 @@ +param( + [string] + $SCTaskNum +) + +#New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred + +#$Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-like', 'VMware Windows Removal for'), '-and', @('state', '-eq', '1') +$Filter = "active=true^short_descriptionLIKEWindows Removal for " +#sysparm_query%3Dactive=true^short_descriptionLIKEWindows Removal for +#$OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter -WarningAction SilentlyContinue | Sort-Object Number + +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter -IncludeTotalCount | Sort-Object {$_.Number.value} + +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object {$_.number.value -EQ $SCTaskNum} +} +$AllRitms = [System.Collections.ArrayList]@() +Write-Verbose -Message ("Number of OpenTasks is " + @($OpenTasks).count) -Verbose + +Connect-ITDvCenter -Credential $Secret:svcitdiaasauto + +ForEach ($OpenTask in $OpenTasks) { + # get SCTask, Ritm + $SCTask = $OpenTask + $SCTaskNum = $OpenTask.number.display_value + Write-Verbose -Message ("Start " + $SCTaskNum) -Verbose + + $short_description = $SCTask.short_description.display_value + $short_description_hostname = $short_description.split(' ')[4] + + $RitmNum = $SCTask.request_item.display_value + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $short_description_hostname) + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Ritm.VariableSet | Where-Object .host_name_ref) -ErrorAction Stop + + Write-Verbose -Message "Gathering VariableSet data from $RitmNum" + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($short_description_hostname -eq $TempCi.FQDN.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + If ($MatchFound -eq $false) { + Write-Error -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -ErrorAction Stop + } + + $HostName = $Ci.Name.display_value + $FQDN = $Ci.FQDN.display_value + + Write-Verbose -Message ("Ci Name " + $Ci.Name.display_value) -Verbose + Write-Verbose -Message ("Ci FQDN " + $Ci.FQDN.display_value) -Verbose + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Unknown'; $hardware_type = 'Other' } + } + + try { + Write-Verbose -Message "Start Removal of $FQDN, $hardware_platform $hardware_type" -Verbose + Remove-ITDWindowsServer -ComputerName $FQDN -SCTaskNum $SCTaskNum -Credential $Secret:svcitdiaasauto -Verbose # $Secret:svcitdiaasauto + #$short_description_new = "$hardware_platform $hardware_type $FQDN is ready for removal." + #Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $short_description; } + #Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{short_description = $short_description_new} + Write-Verbose -Message "End Removal of $FQDN" -Verbose + } + catch { + Write-Error $error[0] + } + Write-Verbose -Message "End $SCTasknum" -Verbose +} +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 new file mode 100644 index 0000000..9cdc2aa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Get-ITDExpiredFiles.ps1 @@ -0,0 +1,13 @@ +Param( + [string] + $ComputerName +) + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + $GetITDExpiredFilesParams = @{ + ComputerName = $ComputerName; + } + Get-ITDExpiredFiles @GetITDExpiredFilesParams -Credential $Secret:ndgov_svcitdpsuwin -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName | Format-Table -AutoSize +} Else { + Get-ITDExpiredFiles -Credential $Secret:ndgov_svcitdpsuwin -Verbose | Select-Object Name,DirectoryName,Extension,LastWriteTime,Length,PSComputerName | Format-Table -AutoSize +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles.ps1 new file mode 100644 index 0000000..d38edf9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.FileManagement/Remove-ITDExpiredFiles.ps1 @@ -0,0 +1,119 @@ + +[CmdletBinding()] +param ( + [string] + $ComputerName, + + [switch] + $WhatIf +) + + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$FilesRemovedSuccess = @() +$FilesRemovedFailure = @() +$GetITDExpiredFilesAutoParams += @{} + +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } +} + +If ($PSBoundParameters.ContainsKey('ComputerName')) { + Write-Verbose -Message "ComputerName parameter found" -Verbose + $GetITDExpiredFilesParams = @{ + Credential = $Secret:ndgov_svcitdpsuwin + } + $GetITDExpiredFilesParams += @{ + ComputerName = $ComputerName; + } +} + +$FilesToRemove = Get-ITDExpiredFiles @GetITDExpiredFilesParams +Write-Verbose -Message ("Found " + $FilesToRemove.count + " expired files to remove") -Verbose + +ForEach ($File in $FilesToRemove) { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName ) + $ComputerName = $File.PSComputerName + $DateTime = Get-Date + $FullName = $File.FullName + + $InvokeCommandParams = @{ + ComputerName = $File.PSComputerName; + #Credential = $Secret:ndgov_svcitdpsuwin; + ErrorAction = 'Stop'; + ArgumentList = @($File.FullName); + ScriptBlock = { Get-Item -Path $args[0] | Remove-Item } + } + + switch ($WhatIf) { + $true { + Write-Verbose -Message "WhatIf switch true" -Verbose + try { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + Write-Host -Message ($Server.ComputerName + " -- " + 'What if: Performing the operation "Remove File" on target ' + $File.FullName) + # log success + $FilesRemovedSuccess += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + }#> + Write-Output $File + } + catch { + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure + $FilesRemovedFailure += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + } + } + Default { + try { + Write-Verbose -Message "WhatIf switch default" -Verbose + Invoke-Command @InvokeCommandParams + Write-Verbose -Message ("Process~" + $File.PSComputerName + "~" + $File.FullName + " removed") + # log success to sql, add obj to array + $SqlQuery = "INSERT INTO [$Table] (PSUJobId, DateTime, ComputerName, Status, FullName) Values ('$PSUJobId', '$DateTime', '$ComputerName', 'Success', '$FullName')" + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + $FilesRemovedSuccess += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + Write-Output $File + } + catch { + Write-Verbose -Message ("Start~" + $File.PSComputerName + "~" + $File.FullName + " failure") + # log failure to sql, add obj to array + $SqlQuery = "INSERT INTO [$Table] (PSUJobId, DateTime, ComputerName, Status, FullName) Values ('$PSUJobId', '$DateTime', '$ComputerName', 'Failure', '$FullName')" + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + $FilesRemovedFailure += [PSCustomObject]@{ + DateTime = $DateTime.tostring("yyyy/MM/dd HH:mm:ss"); + ComputerName = $ComputerName; + FullName = $FullName; + } + } + } + } + + # create CHG request for the work + Write-Verbose -Message "Submit CHG for the work. TBD" -Verbose + + Write-Verbose -Message ("End~" + $File.PSComputerName + "~" + $File.FullName ) -Verbose + ### Generate CHG +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 new file mode 100644 index 0000000..1bec9fe --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Approve-ITDWindowsServer.ps1 @@ -0,0 +1,146 @@ +# cron expression +# 47 8-16 * * 1-5 + +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number.value + Write-Verbose -Message "Start $SCTasknum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + $ComputerName = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $OperatingSystem = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).operating_system + + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + $FormFQDN = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).host_name + $FormHostName = $FormFQDN.split('.')[0] + + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + # Ci does not exist + Write-Verbose -Message ("Ci not found") -Verbose + } + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Other' } + } + + Write-Verbose -Message "Confirm all agents are running" + $ProcessList = @('ccmexec', 'cohesity*', 'nessus*', 'cortex*') + switch ($target_platform) { + 'VMware' { + $ProcessList += 'vmtoolsd' + } + 'Azure' { + Write-Verbose -Message "vmtoolsd not required for Azure VM" + } + Default { + Write-Verbose -Message "no Ci means no platform check" + } + } + } + catch { + Write-Error $error[0] + } + + If ( $ComputerName -like "*.nd.gov" ) { + try { + $AgentCount = 0 + $svcitdpsuwin = Get-ITDPassword -UserName ndgov\svcitdpsuwin -Title ndgov\svcitdpsuwin + $RunningProcess = Invoke-Command -Credential $svcitdpsuwin -ComputerName $FormFQDN -ArgumentList $ProcessList -ErrorAction Stop -ScriptBlock { + Get-Process + } + + If ($RunningProcess) { + ForEach ($ProcessName in $ProcessList) { + If ($RunningProcess -match $ProcessName) { + Write-Verbose -Message "Process $ProcessName found." -Verbose + $AgentCount = $AgentCount + 1 + } + Else { + Write-Warning -Message "Process $ProcessName not found" + # do not increase agentcount count + } + } + } + } + catch [System.Management.Automation.Remoting.PSRemotingTransportException] { + Write-Warning -Message "$FormFQDN unreachable via PSRemoting" + $BuildComplete = $false + } + } Else { + Write-Verbose -Message ($SCTaskNum + $ComputerName + " is not nd.gov, manual agent validation required.") -Verbose + } + + <# if Task has been open for more than x hours, update description for humans to review + $Hours = 6 + If ($SCTask.opened_at.value -lt (Get-Date).AddHours(-$Hours)) { + $work_notes = ("New build Ci has not been found after $Hours hours, problem may have occurred. Please review.`nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $OperatingSystem VM Build for $ComputerName, NEED HUMAN REVIEW" + + <#Update-ServiceNowRecord -ID $SCTask.number -Values @{ + work_notes = $work_notes; + shortdescription = $shortdescription; + } + }#> + + If ($AgentCount -ge @($ProcessList).count) { + Write-Verbose "All required processes running, Windows is ready for use. Update SCTask to notify physical/virtual hardware stakeholders." -Verbose + $work_notes = ("$target_platform $hardware_type $FormFQDN Windows Guest OS complete. `nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $hardware_type $FormFQDN Windows Guest OS complete." + + Write-Verbose -Message "Work notes: $work_notes" -Verbose + Write-Verbose -Message "Short description: $shortdescription" -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $work_notes; + close_notes = "$FQDN $target_platform Windows Guest OS complete."; + short_description = $shortdescription; + state = 'Closed Complete' + } + } + + Write-Verbose -Message "End $SCTasknum" -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 new file mode 100644 index 0000000..da5a051 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmAzure_Manual.ps1 @@ -0,0 +1,130 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + ComputerName = $ComputerName; + AppName = $AppName; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("ComputerName " + $NewITDWindowsVMAzureParams.ComputerName) -Verbose +Write-Verbose -Message ("CPU " + $NewITDWindowsVMAzureParams.CPU) -Verbose +Write-Verbose -Message ("MemoryGB " + $NewITDWindowsVMAzureParams.MemoryGB) -Verbose +Write-Verbose -Message ("DiskOsGB" + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS" + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("Environment" + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName" + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions" + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose + +New-ITDWindowsVmAzure @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 new file mode 100644 index 0000000..d81c74c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/New-ITDWindowsVmVMware_Manual.ps1 @@ -0,0 +1,118 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 50, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskSwapGB = ($MemoryGB + 1), + + [Parameter(ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet = '10.11.12.0/23', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment = 'Test', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Datacenter = 'Mandan', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName = 'ITD-POC-zmeier', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $StartupPriority = 5, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = "No Licensing Restrictions" +) + +switch ($PSCMdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareParams = @{ + ComputerName = $ComputerName; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskSwapGB = $DiskSwapGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + Datacenter = $Datacenter; + AppName = $AppName; + StartupPriority = $StartupPriority; + LicensingRestrictions = $LicensingRestrictions; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmVMwareParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskSwapGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_2_swap_disk ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + Datacenter = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).data_center ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + StartupPriority = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).startup_priority ); + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + } +} + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt server provisioning" -Verbose +Write-Host $NewITDWindowsVmVMwareParams +New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose +Write-Warning -Message "New-ITDWindowsVmVMware function completed" + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Remove-ITDWindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Remove-ITDWindowsServer.ps1 new file mode 100644 index 0000000..54e081c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Remove-ITDWindowsServer.ps1 @@ -0,0 +1,92 @@ +param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = "active=true^short_descriptionLIKEWindows Removal for " +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter -IncludeTotalCount | Sort-Object { $_.Number.value } + +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} +$AllRitms = [System.Collections.ArrayList]@() +Write-Verbose -Message ("Number of OpenTasks is " + @($OpenTasks).count) -Verbose + +# retrieve ndgov\svcitdiaasauto password to be used for Remove-ITDWindowsServer function +$svcitdiaasauto = Get-ITDPassword -Title "IaaS Automation Account" -UserName "ndgov\svcitdiaasauto" + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter + +ForEach ($OpenTask in $OpenTasks) { + # get SCTask, Ritm + $SCTask = $OpenTask + $SCTaskNum = $OpenTask.number.display_value + Write-Verbose -Message ("Start " + $SCTaskNum) -Verbose + + If ($SCTask.work_notes.display_value -like "*needs human review*") { + Write-Verbose -Message ($SCTaskNum + " flagged for human review, skipping...") -Verbose + } + Else { + $short_description = $SCTask.short_description.display_value + $short_description_hostname = $short_description.split(' ')[4] + + $RitmNum = $SCTask.request_item.display_value + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $short_description_hostname) + #$Ci = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Ritm.VariableSet | Where-Object .host_name_ref) -ErrorAction Stop + + Write-Verbose -Message "Gathering VariableSet data from $RitmNum" + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($short_description_hostname -eq $TempCi.FQDN.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + If ($MatchFound -eq $false) { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = 'error during Windows decommission, needs human review' + } + Write-Warning -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -WarningAction Continue + } + + $HostName = $Ci.Name.display_value + $FQDN = $Ci.FQDN.display_value + + Write-Verbose -Message ("Ci Name " + $Ci.Name.display_value) -Verbose + Write-Verbose -Message ("Ci FQDN " + $Ci.FQDN.display_value) -Verbose + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Unknown'; $hardware_type = 'Other' } + } + + try { + Write-Verbose -Message "Start Removal of $FQDN, $hardware_platform $hardware_type" -Verbose + Remove-ITDWindowsServer -ComputerName $FQDN -SCTaskNum $SCTaskNum -Credential $svcitdiaasauto -Verbose + Write-Verbose -Message "End Removal of $FQDN" -Verbose + } + catch { + Write-Error $error[0] + } + Write-Verbose -Message "End $SCTasknum" -Verbose + } +} + +Write-Verbose -Message "Disconnect to vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Test-WindowsServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Test-WindowsServer.ps1 new file mode 100644 index 0000000..e3f1a12 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.General/Test-WindowsServer.ps1 @@ -0,0 +1 @@ +#code goes here \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 new file mode 100644 index 0000000..6223f99 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1 @@ -0,0 +1,145 @@ +[CmdletBinding()] # +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(ParameterSetName = 'FromSCTask')] + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMSizeOverride, + <# + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, +#> + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + FQDN = $FQDN; + AppName = $AppName; + VMSizeOverride = $VMSizeOverride; + #CPU = $CPU; + #MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + VMEnvironment = $VMEnvironment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { + Write-Warning -Message "ResourceGroupNameOverride found $AvailabilityZone" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + 'VMSizeOverride' { + Write-Warning -Message "VMSizeOverride found $VMSizeOverride" + $NewITDWindowsVMAzureParams += @{ VMSizeOverride = $VMSizeOverride } + } + } + If ($NewITDWindowsVmAzureParams.VMSizeOverride) { + # do nothing + } Else { + $NewITDWindowsVMAzureParams += @{ CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors );} + $NewITDWindowsVMAzureParams += @{ MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb );} + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("FQDN " + $NewITDWindowsVMAzureParams.FQDN) -Verbose +Write-Verbose -Message ("CPU " + $NewITDWindowsVMAzureParams.CPU) -Verbose +Write-Verbose -Message ("MemoryGB " + $NewITDWindowsVMAzureParams.MemoryGB) -Verbose +Write-Verbose -Message ("DiskOsGB" + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS" + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("VMEnvironment" + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName" + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions" + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose + +New-ITDWindowsVmAzureStep1 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig new file mode 100644 index 0000000..ebe8f98 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step1.ps1.orig @@ -0,0 +1,151 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] +<<<<<<< HEAD + [string] + $VMSizeOverride, +<<<<<<< HEAD +<# +======= + <# +>>>>>>> main + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] +======= +>>>>>>> 828a9d5a994531efc47fe9ca78c93cfb076c6ba4 + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 128, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB = 20, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Environment, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = 'No Licensing Restrictions', + + [string] + $ResourceGroupNameOverride, + + [ValidateSet('1', '2', '3')] + [int] + $AvailabilityZone +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + ComputerName = $ComputerName; + AppName = $AppName; +<<<<<<< HEAD +<<<<<<< HEAD + VMSizeOverride = $VMSizeOverride; +======= + VMSizeOverride = $VMSizeOverride; +>>>>>>> main + #CPU = $CPU; + #MemoryGB = $MemoryGB; +======= + CPU = $CPU; + MemoryGB = $MemoryGB; +>>>>>>> 828a9d5a994531efc47fe9ca78c93cfb076c6ba4 + DiskOsGB = $DiskOsGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + Environment = $Environment; + LicensingRestrictions = $LicensingRestrictions; + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { $NewITDWindowsVmAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } } + 'AvailabilityZone' { $NewITDWindowsVmAzureParams += @{ AvailabilityZone = $AvailabilityZone } } + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + ComputerName = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + Environment = ( $Ritm.customvariable.environment.value ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + switch ($PSBoundParameters.Keys) { + 'ResourceGroupNameOverride' { + Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ ResourceGroupNameOverride = $ResourceGroupNameOverride } + } + 'AvailabilityZone' { Write-Warning -Message "ResourceGroupNameOverride found $ResourceGroupNameOverride" + $NewITDWindowsVMAzureParams += @{ AvailabilityZone = $AvailabilityZone } + } + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("ComputerName " + $NewITDWindowsVMAzureParams.ComputerName) -Verbose +Write-Verbose -Message ("CPU " + $NewITDWindowsVMAzureParams.CPU) -Verbose +Write-Verbose -Message ("MemoryGB " + $NewITDWindowsVMAzureParams.MemoryGB) -Verbose +Write-Verbose -Message ("DiskOsGB" + $NewITDWindowsVMAzureParams.DiskOsGB) -Verbose +Write-Verbose -Message ("DiskDataGB " + $NewITDWindowsVMAzureParams.DiskDataGB) -Verbose +Write-Verbose -Message ("Subnet " + $NewITDWindowsVMAzureParams.Subnet) -Verbose +Write-Verbose -Message ("OS" + $NewITDWindowsVMAzureParams.OS) -Verbose +Write-Verbose -Message ("Environment" + $NewITDWindowsVMAzureParams.Environment) -Verbose +Write-Verbose -Message ("AppName" + $NewITDWindowsVMAzureParams.AppName) -Verbose +Write-Verbose -Message ("LicensingRestrictions" + $NewITDWindowsVMAzureParams.LicensingRestrictions) -Verbose + +New-ITDWindowsVmAzureStep1 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 new file mode 100644 index 0000000..8c83026 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmAzure_Step2.ps1 @@ -0,0 +1,49 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN +) + +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmAzureParams = @{ + FQDN = $FQDN; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + Write-Verbose -Message "New-ITDServiceNowSession" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmAzureParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + AppName = ( (Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).application_info).Name.display_value); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + } + } +} + +Write-Verbose -Message "Connect to Azure using Service Principal" -Verbose +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +Write-Verbose -Message "NewITDWindowsVMAzureParams:" -Verbose +Write-Verbose -Message ("FQDN " + $NewITDWindowsVMAzureParams.FQDN) -Verbose + +New-ITDWindowsVmAzureStep2 @NewITDWindowsVmAzureParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 new file mode 100644 index 0000000..3b7c1fa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step1.ps1 @@ -0,0 +1,144 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $CPU = 1, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $MemoryGB = 4, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskOsGB = 50, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $DiskSwapGB = ($MemoryGB + 1), + + [Parameter(ParameterSetName = 'ManualEntry')] + [int] + $DiskDataGB, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Subnet = '10.11.12.0/23', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $OS = 'Windows Server 2022 Datacenter', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment = 'Test', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $Datacenter = 'Mandan', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName = 'ITD-POC-zmeier', + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [int] + $StartupPriority = 5, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $LicensingRestrictions = "No Licensing Restrictions" +) + +switch ($PSCMdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareParams = @{ + FQDN = $FQDN; + CPU = $CPU; + MemoryGB = $MemoryGB; + DiskOsGB = $DiskOsGB; + DiskSwapGB = $DiskSwapGB; + DiskDataGB = $DiskDataGB; + Subnet = $Subnet; + OS = $OS; + VMEnvironment = $VMEnvironment; + Datacenter = $Datacenter; + AppName = $AppName; + StartupPriority = $StartupPriority; + LicensingRestrictions = $LicensingRestrictions; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + + $NewITDWindowsVmVMwareParams = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + CPU = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).processors ); + MemoryGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).memory_gb ); + DiskOsGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_1_os ); + DiskSwapGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_2_swap_disk ); + DiskDataGB = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).disk_3 ); + Subnet = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).cidr_block).name.display_value; + OS = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).target_os_version_windows ); + VMEnvironment = ( $Ritm.customvariable.environment.value ); + Datacenter = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).data_center ); + AppName = ( Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq "$FqdnFromSCTaskDescription" }).application_info).name.display_value; + StartupPriority = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).startup_priority ); + LicensingRestrictions = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).licensing_restrictions ); + } + } +} + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt server provisioning" -Verbose +Write-Host $NewITDWindowsVmVMwareParams +try { + New-ITDWindowsVmVMwareStep1 @NewITDWindowsVmVMwareParams -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Verbose -Message "New-ITDWindowsVmVMwareStep1 function completed" + $Step1Complete = $true +} +catch { + Write-Error -Message $error[0] + $Step1Complete = $false + throw +} + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + Write-Verbose -Message ("Update " + $SCTaskNum + " with Step 1 status") -Verbose + switch ($Step1Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 1 complete. `nPSU Job Id #" + $UAJob.Id) + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 1 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 new file mode 100644 index 0000000..78cf35a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVmVMware_Step2.ps1 @@ -0,0 +1,87 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTask')] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $AppName, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $VMEnvironment +) + +switch ($PSCMdlet.ParameterSetName) { + 'ManualEntry' { + $NewITDWindowsVmVMwareStep2Params = @{ + FQDN = $FQDN; + AppName = $AppName; + VMEnvironment = $VMEnvironment; + } + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + Write-Verbose -Message ("Ritm: " + $Ritm.Number) -Verbose + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + Write-Verbose -Message ("FqdnFromSCTaskDescription: " + ($SCTask.short_description).display_value.split(' ')[7] ) -Verbose + $NewITDWindowsVmVMwareStep2Params = @{ + FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ); + VMEnvironment = ( ($Ritm.CustomVariable).environment.value ); + AppName = ( (Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).application_info).Name.display_value); + } + + Write-Verbose -Message ("Params FQDN: " + $NewITDWindowsVmVMwareStep2Params.FQDN) -Verbose + } +} + + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdiaasauto -Verbose + +Write-Verbose -Message "Attempt VMware step 2" -Verbose +Write-Host $NewITDWindowsVmVMwareStep2Params +try { + New-ITDWindowsVmVMwareStep2 @NewITDWindowsVmVMwareStep2Params -Credential $Secret:ndgov_svcitdiaasauto -Verbose + Write-Warning -Message "New-ITDWindowsVmVMwareStep2 function completed" + $Step2Complete = $true +} +catch { + Write-Error -Message $error[0] + $Step2Complete = $false + throw +} + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter + +switch ($PSCmdlet.ParameterSetName) { + 'FromSCTask' { + switch ($Step2Complete) { + $true { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VM build step 2 complete. `nPSU Job Id #" + $UAJob.Id); + } + } + $false { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("VMware build step 2 errored, needs human review. `nPSU Job Id #" + $UAJob.Id) + } + } + } + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 new file mode 100644 index 0000000..aa1ece0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Auto.ps1 @@ -0,0 +1,146 @@ +<# +.SYNOPSIS + Processes automated server build tasks for Windows machines in ServiceNow, triggered via PowerShell Universal. +.DESCRIPTION + This script connects to the ServiceNow API, retrieves open catalog tasks that match a specific filter for automated server build tasks, + and processes them. This script is designed to run as a scheduled task. It can optionally filter tasks by a specific SCTask number. +.PARAMETER SCTaskNum + The ServiceNow task number to filter the tasks. If not provided, all tasks matching the filter will be processed. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 + This example runs the script and processes all open tasks that match the filter for automated server build tasks. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 -SCTaskNum 'SCTASK0012345' + This example runs the script and processes only the task with the specified SCTask number. +.NOTES + Ensure that the ServiceNow instance URL and credentials are correctly configured in the New-ITDServiceNowSession function. + This script is not supported in Linux. +#> + +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + <# + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } +#> + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + { $_ -match "human review" } { + Write-Verbose -Message "Human review required, skipping" -Verbose + Break + } + { $_ -match "build step 2 complete" } { + # execute Step 3 + Write-Verbose -Message "Step 2 already complete, starting step 3" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVm_Step3.ps1" -SCTaskNum $SCTaskNum + #$WorkNotesMsg = ("VMware build Step 3 started.`nPSU Job Id #" + $PSUJob.Id) + Break + } + { $_ -match "build Step 2 started"} { + Write-Verbose -Message "Step 2 already started, skipping" -Verbose + Break + } + { $_ -match "build step 1 complete" } { + # execute Step 2 + Write-Verbose -Message "Step 1 already complete, starting Step 2" -Verbose + # Determine if VMware or Azure and run appropriate build Step 2 function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step2.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmVMware_Step2.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + { $_ -match "build Step 1 started"} { + Write-Verbose -Message "Step 1 already started, skipping" -Verbose + Break + } + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmVMware_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + If($null -eq $WorkNotesMsg){ + # do nothing + } Else { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{work_notes = $WorkNotesMsg } + } + + Write-Verbose -Message "End $SCTaskNum" -Verbose +} + +#> + +#Invoke-PSUScript -Name New-ITDWindowsVmVMware_Step1.ps1 -SCTaskNum "SCTASK0310457" + + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 new file mode 100644 index 0000000..c53bec4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ITD-WindowsServer.Lifecycle/New-ITDWindowsVm_Step3.ps1 @@ -0,0 +1,126 @@ +# used by both Azure and VMware build tasks + +[CmdletBinding()] +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'FromSCTASK')] + [string] + $SCTaskNum, + + [Parameter(Mandatory = $true, ParameterSetName = 'ManualEntry')] + [string] + $FQDN +) + +# get FQDN from SCTask/Ritm, or directly from user input +switch ($PSCmdlet.ParameterSetName) { + 'ManualEntry' { + Write-Verbose -Message "FQDN manually entered" + } + 'FromSCTask' { + Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { $ServiceNowEnvironment = 'Test' } + + "ITDWINAUTOP1" { $ServiceNowEnvironment = 'Production' } + } + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -IncludeCustomVariable + Write-Verbose -Message ("Ritm: " + $Ritm.Number) -Verbose + + $FqdnFromSCTaskDescription = ($SCTask.short_description).display_value.split(' ')[7] + Write-Verbose -Message ("FqdnFromSCTaskDescription: " + ($SCTask.short_description).display_value.split(' ')[7] ) -Verbose + + $FQDN = ( ($Ritm.VariableSet | Where-Object { $_.host_name -eq $FqdnFromSCTaskDescription }).host_name ).tolower(); + $OperatingSystem = ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).operating_system + } +} + +try { + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } +<# Is this needed? + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + # Ci does not exist + Write-Verbose -Message ("Ci not found") -Verbose + } + + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Other' } + } +#> + Write-Verbose -Message "Confirm all required agents are running" + $ProcessList = @('ccmexec', 'cohesity*', 'nessus*', 'cortex*') + switch ($target_platform) { + 'VMware' { + $ProcessList += 'vmtoolsd' + } + 'Azure' { + Write-Verbose -Message "No Azure specific agents to check for" -Verbose + } + Default { + Write-Verbose -Message "no Ci means no platform check" + } + } +} +catch { + Write-Error $error[0] +} + +If ( $FQDN -like "*.nd.gov" ) { + try { + $AgentCount = 0 + $svcitdpsuwin = Get-ITDPassword -UserName ndgov\svcitdpsuwin -Title ndgov\svcitdpsuwin + $RunningProcess = Invoke-Command -Credential $svcitdpsuwin -ComputerName $FQDN -ErrorAction Stop -ScriptBlock { + Get-Process + } + + If ($RunningProcess) { + ForEach ($ProcessName in $ProcessList) { + If ($RunningProcess -match $ProcessName) { + Write-Verbose -Message "Process $ProcessName found." -Verbose + $AgentCount = $AgentCount + 1 + } + Else { + Write-Warning -Message "Process $ProcessName not found" + # do not increase agentcount count + } + } + } + } + catch [System.Management.Automation.Remoting.PSRemotingTransportException] { + Write-Warning -Message "$FQDN unreachable via PSRemoting" + $BuildComplete = $false + } +} +Else { + Write-Verbose -Message ($SCTaskNum + $ComputerName + " is not nd.gov, manual agent validation required.") -Verbose +} + +If ($AgentCount -ge @($ProcessList).count) { + Write-Verbose "All required processes running, Windows is ready for use. Update SCTask to notify physical/virtual hardware stakeholders." -Verbose + $work_notes = ("$target_platform $hardware_type $FQDN Windows Guest OS complete. `nPSU Job Id #" + $UAJob.Id) + $shortdescription = "$target_platform $hardware_type $FQDN Windows Guest OS complete." + + Write-Verbose -Message "Work notes: $work_notes" -Verbose + Write-Verbose -Message "Short description: $shortdescription" -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $work_notes; + close_notes = "$FQDN $target_platform Windows Guest OS complete."; + short_description = $shortdescription; + state = 'Closed Complete' + } +} + +Write-Verbose -Message "End $SCTasknum" -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 new file mode 100644 index 0000000..254219d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Add-ITDADUserSPN.ps1 @@ -0,0 +1,96 @@ +<# +.SYNOPSIS + Add Service Principal Name to a ITD AD Service Account +.DESCRIPTION + Add Service Principal Name to a ITD AD Service Account +.NOTES + example using setspn: + setspn.exe -s MSSQLSvc/test.nd.gov:1433 ndgov\svctest + setspn.exe -s MSSQLSvc/test:1433 ndgov\svctest + setspn.exe -s MSSQLSvc/test.nd.gov ndgov\svctest + setspn.exe -s MSSQLSvc/test ndgov\svctest + + setspn.exe -s MSSQLSvc/test.nd.gov ndgov\svctest +.LINK + +#> + +[CmdletBinding()] +Param( + [string] + $SamAccountName, + + [Parameter(HelpMessage = "Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $ServicePrincipalName = $null +) + +Write-Verbose -Message "Prep Variables and Connections" +switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { + $ServiceNowEnvironment = 'Test' + } + "ITDWINAUTOP1" { + $ServiceNowEnvironment = 'Production' + } +} +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id +$StartDateTime = Get-Date + +Write-Verbose -Message "Find AD User" -Verbose +$ADUser = Get-ADUser -Identity $SamAccountName -ErrorAction Stop + +Write-Verbose -Message "Add SPN(s)" -Verbose +try { + $ServicePrincipalName | ForEach-Object { + Write-Verbose -Message ("Attempt to add SPN value " + $_) -Verbose + $ADUser | Set-ADUser -ServicePrincipalNames @{Add=$_} + } +} +catch { + Write-Error $Error[0] +} + +Start-Sleep -Seconds 2 + +Write-Verbose -Message "No errors when adding the SPNs, listing the SPNs here for human validation" -Verbose +$ValidateUser = Get-ADUser -Identity $SamAccountName -Properties ServicePrincipalNames | Select-Object SamAccountName, ServicePrincipalNames +$ValidateUser.ServicePrincipalNames + +Write-Verbose -Message "Generate ServiceNow CHG" -Verbose +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose + +New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred -Verbose +$NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "ServicePrincipalName added to ndgov\$SamAccountName - PSU Job Id $PSUJobId"; + Description = "ServicePrincipalName added to ndgov\$SamAccountName - PSU Job Id $PSUJobId, see notes for details"; + Justification = "ServicePrincipalName is required to be added to Active Directory Service Accounts by some applications"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Remove the new service principal name from the serviceprincipalname attribute." + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; +} + +$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose +$CHGNum = $CHG.Number.value + +Write-Verbose -Message ("Completing SNow " + $CHG.Number.value) -Verbose +$CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = "ServicePrincipalNames added to ndgov\$SamAccountName - PSU Job Id $PSUJobId`n" + ($ServicePrincipalName | ForEach-Object {$_}) +} +Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDADUser_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDADUser_script.ps1 new file mode 100644 index 0000000..5636a0e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDADUser_script.ps1 @@ -0,0 +1,9 @@ +[CmdletBinding()] +Param( + [string] + $Identity +) + +If($Identity){ + Get-ADUser -Identity $Identity -Properties LockedOut,MemberOf + } diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDPassword_test.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDPassword_test.ps1 new file mode 100644 index 0000000..5083956 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Get-ITDPassword_test.ps1 @@ -0,0 +1,30 @@ +$Title = 'itdwinautot1.nd.gov' +$Username = 'svczmtest005' +$Credential = $Secret:svcitdiaasauto +$FullRecord = $false +ConvertTo-SecureString -String "things" -AsPlainText -Force +$Uri = 'https://itdpv.nd.gov/winapi/searchpasswords/?' + +If ($Title) { $Uri += 'title=' + $Title + '&' } +If ($UserName) { $Uri += 'username=' + "$UserName" + '&' } +$Uri = $Uri.TrimEnd('&') + +$InvokeResult = Invoke-RestMethod -Method Get -Uri $Uri -Credential $Credential + +$OutResult = $InvokeResult | Select-Object PasswordListID, PasswordList, PasswordID, Title, Description, UserName, @{n = 'SecurePassword'; e = { $_.Password | ConvertTo-SecureString -AsPlainText -Force } }, AccountTypeId, AccountType + +If (@($OutResult).count -eq 1) { + If ($PSCmdlet.ParameterSetName -eq "ToClipboard") { + $InvokeResult.Password | Set-Clipboard + } + If ($FullRecord) { + Write-Output $OutResult + } + Else { + $OutCred = New-Object System.Management.Automation.PSCredential($OutResult.UserName, $OutResult.SecurePassword) + Write-Output $OutCred + } +} +Else { + Write-Output $OutResult +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 new file mode 100644 index 0000000..8f7fa42 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDADServiceAccount.ps1 @@ -0,0 +1,134 @@ +<# +.SYNOPSIS + Creates an Active Directory user/service account for the nd.gov domain +.DESCRIPTION + Creates an Active Directory user/service account for the nd.gov domain. +.NOTES + The PasswordstateList parameter must be validated. If a Passwordstate Password List to the options, ensure that the ndgov\svcitdiaasauto Active Directory has modify access on the Password List. + + Requires Integrated or Agent environment. If not chosen, an erroneous error is caused during the invocation of New-ITDADServiceAccount when the PSCredential object is created to be returned to the user, see below. + [error] Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value." + The agent environment is selected to reduce parameter during script execution, and Run As Credential is enforced as svcitdpsuwin +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0016867 +#> + +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true, + HelpMessage = "Only nd.gov domain is supported at this time.")] + [ValidateSet("nd.gov")] + [string] + $DomainName = 'nd.gov', + + [Parameter(Mandatory = $true, + HelpMessage = "This is the account name. This value will also be set on the Active Directory Surname attribute (GivenName or Surname are required for ServiceNow lookups)")] + [string] + $SamAccountName, + + [Parameter(Mandatory = $true, + HelpMessage = "Will be set on the respective Passwordstate record property and Active Directory attribute. '1120' will automatically be appended to the entry.")] + [string] + $Description, + + [Parameter(Mandatory = $true, + HelpMessage = "What goes into the Passwordstate record Title field. Generally a FQDN for the server that will use this service account.")] + [string] + $PasswordstateTitle, + + [Parameter(Mandatory = $true, + HelpMessage = "The Passwordstate Password List where the credentials to be saved. Go here to retrieve the password for the new account.")] + [ValidateSet('CSRC', 'VMware_Systems','Peoplesoft Share PW')] + [string] + $PasswordstateList +) + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$StartDateTime = (Get-Date) +$EndDateTime = $StartDateTime.AddMinutes(1) + +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch ($UAJob.ComputerName) { + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_ActiveDirectory_Object_NewITDADServiceAccount_NPD" + $ServiceNowEnvironment = 'Test' + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_ActiveDirectory_Object_NewITDADServiceAccount_PRD" + $ServiceNowEnvironment = 'Production' + } +} + +Write-Verbose -Message "fix samaccountname" -Verbose +$SamAccountName = $SamAccountName.Tolower() + +# add to SQL +Write-Verbose -Message "Add request to SQL" -Verbose +$SqlQuery = "INSERT INTO [$SnapshotTable] (PSUJobId,RequestedBy,DateTime,Status,DomainName,SamAccountName,Description,PasswordstateTitle,PasswordstateList) Values ('$PSUJobId', '$RequestedBy', '$StartDateTime','Requested','$DomainName','$SamAccountName', '$Description', '$PasswordstateTitle', '$PasswordstateList');" +Write-Verbose -Message $SqlQuery -Verbose +Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +# Do the work +Write-Verbose -Message "Create the account in Active Directory, and Passwordstate record" -Verbose +New-ITDADServiceAccount -SamAccountName $SamAccountName -Description $Description -PasswordstateList $PasswordstateList -PasswordstateTitle $PasswordstateTitle -Credential $Secret:ndgov_svcitdpsuad -Verbose +Write-Verbose -Message "Executing Get-ADUser -Identity $SamAccountName" -Verbose + +# Validate the user +$ADUser = Get-ADUser -Identity $SamAccountName +If ($ADUser) { + Write-Output $ADUser + + Write-Verbose -Message "Create CHG request for the work" -Verbose + New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + $NewITDServiceNowChangeRequestParams = @{ + TemplateName = 'NDIT-SPS-Server Add/Chg/Del' + RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv'; + Category = 'Systems Platforms - Systems'; + Subcategory = 'Windows'; + Impact = 3; + ShortDescription = "New $DomainName Active Directory service account $SamAccountName created - PSU Job Id $PSUJobId"; + Description = "New $DomainName Active Directory service account $SamAccountName created"; + Justification = "New $DomainName Active Directory service account required for zero-trust policies, following guidelines found in KB0016867"; + Implementation = "PSUniversal execution"; + RiskImpactAnalysis = "Low"; + BackoutPlan = "Delete the new user account" + TestPlan = "n/a" + WhoIsImpacted = "Windows System Administrators"; + StartTime = $StartDateTime + EndTime = $StartDateTime.AddMinutes(1); + AssignmentGroup = 'NDIT-Computer Systems Windows'; + ChangeManagerUsername = 'khellman'; + ChangeCoordinatorUsername = 'gpgolberg'; + AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv'; + } + + $CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose + $CHGNum = $CHG.Number.value + + Write-Verbose -Message ("Completing SNow " + $CHG.Number.value) -Verbose + $CompleteITDServiceNowChangeRequestParams = @{ + Number = $CHG.Number.value + CloseCode = "Successful" + CloseNotes = ("New $DomainName Active Directory account " + $obj.ADDomain + "\" + $obj.SamAccountName + " created.") + } + Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose + + Write-Verbose -Message "Status Success" -Verbose + $SQLStatus = "Succcess" +} +Else { + Write-Verbose -Message "Status Failure" -Verbose + $SQLStatus = "Failure" +} +#> + +Write-Verbose -Message "Update SQL with that CHG num and update Status" -Verbose +$SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = '$SQLStatus', SNowCHGNum = '$CHGNum' WHERE PSUJobId = " + $PSUJobId) +Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDPassword_test.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDPassword_test.ps1 new file mode 100644 index 0000000..2b28c55 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/New-ITDPassword_test.ps1 @@ -0,0 +1,31 @@ +Param ( + [string] + $PasswordstateList, + + [string] + $PasswordstateTitle, + + [string] + $Description, + + [string] + $UserName +) + +$Credential = $Secret:svcitdiaasauto + +$NewITDPasswordParams = @{ +PasswordList = $PasswordstateList; +Title = $PasswordstateTitle; +Description = $Description; +UserName = ("ndgov\$SamAccountName"); +Credential = $Credential; +} + +switch ($PSBoundParameters.Keys) { +PasswordStateNotes { + $NewITDPasswordParams.Notes = $PasswordstateNotes +} +} + +$NewITDPasswordResult = New-ITDPassword @NewITDPasswordParams -ErrorAction Stop \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Remove-ITDADUser.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Remove-ITDADUser.ps1 new file mode 100644 index 0000000..e3f1a12 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Remove-ITDADUser.ps1 @@ -0,0 +1 @@ +#code goes here \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Set-ITDSPN.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Set-ITDSPN.ps1 new file mode 100644 index 0000000..e035ea3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-ActiveDirectory.Object/Set-ITDSPN.ps1 @@ -0,0 +1 @@ +# It all starts with a single line of powershell code. \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 new file mode 100644 index 0000000..93b5ae6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Add-ITDSolarwindsNode.ps1 @@ -0,0 +1,31 @@ +Param( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName = $null, + + [ValidateSet('All Day Every Day', + 'Weekdays 700 to 1800', + 'All Week 500 to 2300' + )] + [string] + $SupportHours + +) + +$Func = { + param($C, $SwSupportHours) + Write-Verbose -Message "Add to Solarwinds" -Verbose + Import-SWDiscovery -ComputerName $C -Integration ServiceNow + + Start-Sleep -Seconds 10 + + Write-Verbose -Message "Set Solarwinds node custom properties if parameter exists" -Verbose + If($PSBoundParameters.ContainsKey('SupportHours')){ + Write-Verbose -Message "SupportHours $SwSupportHours." -Verbose + Set-SWNodeCustomProperty -ComputerName $C -Property SupportHours -Value $SwSupportHours + } +} + +$ComputerName | ForEach-Object { + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $_,$SupportHours -Credential $Secret:ndgov_svcitdiaasauto +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 new file mode 100644 index 0000000..5363e61 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Remove-ITDSolarwindsNode.ps1 @@ -0,0 +1,10 @@ +Param( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName +) + +ForEach ($cn in $ComputerName) { + Write-Verbose -Message "Attempt Solarwinds removal for $cn" -Verbose + Remove-ITDSolarwindsNode -ComputerName $cn -Credential $Secret:ndgov_svcitdiaasauto -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 new file mode 100644 index 0000000..6b82563 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Monitoring-Solarwinds/Update-ITDSolarwindsNodeFromSNowRitm.ps1 @@ -0,0 +1,38 @@ +Write-Verbose -Message "Prepare variables based on PSU server" -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServiceNowEnvironment = "Test" + } + "ITDWINAUTOP1" { + $ServiceNowEnvironment = "Production" + } +} +New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred + +<# +Write-Verbose -Message "Retrieve List of all Server Build Request request items from ServiceNow where closed_at is Yesterday and request_type is Change" -Verbose +$Filter = 'cat_item=c64e27af47244610b7853238436d435d^variables.3bf9fc3b47240a10b7853238436d430b=Change^closed_atONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()' +####### 'cat_item=c64e27af47244610b7853238436d435d^variables.3bf9fc3b47240a10b7853238436d430b=Change^closed_atONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()' +$CompletedRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter + +Write-Verbose -Message ("Found " + @($CompletedRitms).count + " completed Ritms.") +#> + +$CompletedRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number RITM0269022 +ForEach($Ritm in $CompletedRITMs){ + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number ($Ritm.number.value) -IncludeCustomVariable -IncludeVariableSet + # loop each VM row + ForEach($row in $Ritm.VariableSet){ + # resolve sys_id to host name + $CmdbCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId $row.host_name_ref + Write-Verbose -Message ("Start " + $Ritm.number.value + " server " + $row.host_name_ref + ', ' + $CmdbCi.fqdn.display_value) -Verbose + + # run solarwinds import + $Func = { + param ($c) + Write-Verbose -Message "Attempting to import $c to Solarwinds" + Import-SWDiscovery -ComputerName $c + } + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $CmdbCi.fqdn.display_value -Credential $Secret:ndgov_svcitdiaasauto + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 new file mode 100644 index 0000000..5a539d6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/New-ITDPSUScript.ps1 @@ -0,0 +1,34 @@ +Param( + [string] + $Name, + + [ValidateSet( + 'Infra-ActiveDirectory.Object', + 'Infra-Azure.VirtualMachine', + 'Infra-Monitoring-Solarwinds', + 'Infra-VMware.Administration', + 'Infra-VMware.VirtualMachine', + 'Infra-VMware.Snapshot', + 'ITD-WindowsServer.FileManagement', + 'ITD-WindowsServer.General', + 'ITD-WindowsServer.Lifecycle', + 'Shared-Powerschool' + )] + [string] + $Path +) + +switch ($Path){ + <# example switch condition and actions + { $_ -like "App-XXXXX"} {$TagNamesEnforced = @('Shared-XXXXX_Modify)} + #> + { $_ -eq "Infra-ActiveDirectory.Object" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Infra-Azure.*"} {$TagNamesEnforced = @('Infra-VMware_Modify')} + { $_ -like "Infra-Monitoring-Solarwinds*" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Infra-VMware*" } { $TagNamesEnforced = @('Infra-VMware_Modify') } + { $_ -like "ITD-WindowsServer*" } { $TagNamesEnforced = @('ITD-WindowsServer_Modify') } + { $_ -like "Shared-PowerSchool*" } { $TagNamesEnforced = @('Shared-PowerSchool_Modify') } + +} +New-PSUScript -Name $Name -Path "$Path\$Name" -Tag @($TagNamesEnforced) -ScriptBlock {# It all starts with a single line of powershell code. +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 new file mode 100644 index 0000000..e6e7554 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-Servers-PowerShellUniversal/Update-ITDModule.ps1 @@ -0,0 +1,42 @@ +####### +Write-Verbose -Message "Determine if ITD_PwshGallery is registered" -Verbose +If(Get-PSRepository -Name ITD_PwshGallery -ErrorAction SilentlyContinue){ + Write-Verbose -Message "ITD_PwshGallery found." -Verbose +} Else { + $RegisterPSRepositoryParams = @{ + Name = 'ITD_PwshGallery'; + InstallationPolicy = 'Trusted'; + SourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + PublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptSourceLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + ScriptPublishLocation = 'https://powershell.nd.gov/ITD_PwshGallery/nuget/'; + } + Register-PSRepository @RegisterPSRepositoryParams +} + +Write-Verbose -Message "Retrieve list of all available modules and versions" +$ITDModules = Find-Module -Name "ITD.*" -Repository ITD_PwshGallery + + +Write-Verbose -Message "Compare local module versions to repository versions, and update if needed" +ForEach($ITDModule in $ITDModules){ + $VersionsAvailable = $null + $MostRecentVersion = $null + $RepoVersion = $null + + $VersionsAvailable = Get-Module -Name $ITDModule.name -ListAvailable + $MostRecentVersion = $VersionsAvailable | Sort-Object Version -Descending | Select -First 1 + $RepoVersion = $ITDModule.Version + + If($null -eq $MostRecentVersion) { + Write-Verbose -Message ($ITDModule.Name + " was not found locally, installing module now.") -Verbose + Install-Module -Name $ITDModule.Name -Scope AllUsers -Repository ITD_PwshGallery + } Else { + Write-Verbose -Message ($ITDModule.Name + " was found locally, comparing versions and updating if needed..") -Verbose + Write-Host -Message ($ITDModule.Name) + Write-Host -Message ("Local version is " + $MostRecentVersion.Version) + Write-Host -Message ("The Repo version is " + $RepoVersion) + Write-Host -Message ("") + Update-Module -Name $ITDModule.Name -Scope AllUsers -Verbose + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 new file mode 100644 index 0000000..e035ea3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareLunIdNextAvailable.ps1 @@ -0,0 +1 @@ +# It all starts with a single line of powershell code. \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 new file mode 100644 index 0000000..2c52aa5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Get-ITDVMwareVMGuestIPsForPA.ps1 @@ -0,0 +1,131 @@ +<# +.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 +#> + + + +<# Scheduled Task metadata +General + Get IPs for PA + run as ndgov\!itdvcenterppa + run whether user is logged on or not + Triggers + Daily, 11am + Daily, 11pm +Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1" + new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetVMwareVMGuestIPsForPA\GetVMwareVMGuestIPsForPA.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + +#Connect +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + + +##Windows + + +#Output File +$OutFileWin = "c:\inetpub\wwwroot\Win.txt" +#$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileWin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Win\$Timestamp-Win.txt" +Remove-Item $OutFileWin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "windows7Guest" ` + -or $_.GuestID -eq "windows7_64Guest" ` + -or $_.GuestID -eq "windows7Server64Guest" ` + -or $_.GuestID -eq "windows8_64Guest" ` + -or $_.GuestID -eq "windows8Server64Guest" ` + -or $_.GuestID -eq "windows9Server64Guest" ` + -or $_.GuestID -eq "winLonghorn64Guest" ` + -or $_.GuestID -eq "winLonghornGuest" ` + -or $_.GuestID -eq "winNetStandardGuest" ` + -or $_.GuestID -eq "winNetEnterpriseGuest" ` + -or $_.GuestID -eq "windows9_64Guest" ` + -or $_.GuestID -eq "windows2019srv_64Guest" ` + -or $_.GuestID -eq "windows2019srvNext_64Guest") } +$vmviewwin = $vmwin | Get-View + +$Outputwin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewwin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputWin += $IP + "`n" + } + } + } +} + +#If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline} +If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline } + + + +##Linux + +#Output File +$OutFileLin = "c:\inetpub\wwwroot\Lin.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileLin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Lin\$Timestamp-Lin.txt" +Remove-Item $OutFileLin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "centos6_64Guest" ` + -or $_.GuestID -eq "centos64Guest" ` + -or $_.GuestID -eq "centos7_64Guest" ` + -or $_.GuestID -eq "oracleLinux64Guest" ` + -or $_.GuestID -eq "oracleLinux7_64Guest" ` + -or $_.GuestID -eq "rhel4Guest" ` + -or $_.GuestID -eq "rhel5Guest" ` + -or $_.GuestID -eq "rhel5_64Guest" ` + -or $_.GuestID -eq "rhel6Guest" ` + -or $_.GuestID -eq "rhel6_64Guest" ` + -or $_.GuestID -eq "rhel7_64Guest" ` + -or $_.GuestID -eq "rhel8_64Guest" ` + -or $_.GuestID -eq "rhel9_64Guest" ` + -or $_.GuestID -eq "sles11_64Guest" ` + -or $_.GuestID -eq "sles12_64Guest" ` + -or $_.GuestID -eq "ubuntu64Guest") } +$vmviewlin = $vmLin | Get-View + +$OutputLin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewlin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputLin += $IP + "`n" + } + } + } +} + +#If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline} +If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline } + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Sync-ITDVMwareVMToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Sync-ITDVMwareVMToSql.ps1 new file mode 100644 index 0000000..0ad8d69 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Administration/Sync-ITDVMwareVMToSql.ps1 @@ -0,0 +1,67 @@ +<# This is how VMware data is sent to Billing + +Scheduled Task metadata +General + Old-VMware Billing + run as ndgov\!itdvcenterscript (required for SQL Database access) + run whether user is logged on or not + Triggers + Daily, 5am +Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\vmconfig.ps1" + new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1" + "C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1" + newV3 - PSUniversal script and schedule + +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop + +SQL Query to check for most recent 2500 records +SELECT TOP (2500) [ServerName] + ,[SnapshotDate] + ,[VMName] + ,[Memory_MB] + ,[Num_VCPU] + ,[Disk_MB] + ,[ESXHostName] + FROM [ITD-SRS-Billing].[dbo].[VMWare_VCenter_VMs] + ORDER BY SnapshotDate DESC, VMName ASC + +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" +#Start-Transcript F:\SyncVMwareVMsToSql\Logs\SyncVMwareVMsToSql-$Timestamp.log + +Write-Verbose -Message "Connect to vCenter" -Verbose +Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +Write-Verbose -Message "Get current virtual machines, minus filters" +$Datacenters = Get-Datacenter | Where-Object {$_.Name -notlike "*Normandy*" -and $_.Name -notlike "*Vantis*"} +$VMs = $Datacenters | Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "itdzmtest*"} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name + +Write-Verbose "Prep SQL connection" -Verbose +$SqlServer = "itdsql22p1.nd.gov\SQL22P1" +$Database = "ITD-SRS-Billing" +$Date = "'" + (Get-Date).ToString('yyyy/MM/dd') + "'" + +Write-Verbose -Message "Remove today's entries from SQL if already there" +$SqlQuery = "delete from [VMware_VCenter_VMs] where snapshotdate = $Date;" +Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery + +Write-Verbose -Message "Start loop to create new record for each VM found" -Verbose +foreach($VM in $VMs) { + Write-Verbose -Message ("Begin " + $VM.Name) + $VMName = "'" + $VM.Name + "'" + $VMMemoryMB = $VM.MemoryMB + $VMNumCPU = $VM.NumCPU + $VMHardDiskSizeGB = $VM.HardDiskSizeGB + $VMHost = "'" + $VM.VMHost + "'" + $SqlQuery ="INSERT INTO [VMware_VCenter_VMs] (ServerName, SnapshotDate, VMName, Memory_MB, Num_VCPU, Disk_MB, ESXHostName) Values ('None', $Date, $VMName, $VMMemoryMB, $VMNumCPU, $VMHardDiskSizeGB, $VMHost);" + Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery +} + +#Stop-Transcript +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareSnapshotTask.ps1 new file mode 100644 index 0000000..4548656 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareSnapshotTask.ps1 @@ -0,0 +1,133 @@ +<# +.SYNOPSIS + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.DESCRIPTION + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.NOTES + +.LINK + https://northdakota.service-now.com/nav_to.do?uri=kb_knowledge.do?sysparm_query=number=KB0017146 +#> + +[CmdletBinding()] +param ( + [Parameter( + Mandatory = $true, + HelpMessage = "The VMware virtual machine name. This is most commonly the FQDN. You can verify the virtual machine name by logging into vCenter. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back." + )] + [string[]] + $VMName, + + [Parameter(Mandatory = $true, + HelpMessage = "The DateTime you want the snapshot to occur.")] + [datetime] + $DateTime = (Get-Date), + + [Parameter(Mandatory = $true, + HelpMessage = "How many hours the snapshot will exist. The snapshot will be automatically deleted after the duration. Maximum value is 72 hours.")] + [ValidateRange(1, 72)] + [int] + $DurationHours = 4, + + [Parameter(HelpMessage = "Email address that you want vCenter to notify when the snapshot is taken. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $Email +) + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$StartDateTime = $DateTime +$EndDateTime = $StartDateTime.AddHours($DurationHours) +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +$StartDateTimeSql = $StartDateTime.ToString('yyyy/MM/dd HH:mm:ss') +$EndDateTimeSql = $EndDateTime.ToString('yyyy/MM/dd HH:mm:ss') + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr +Write-Verbose -Message "After Connect vCenter" -Verbose + + +ForEach ($name in $VMName) { + Write-Verbose -Message ("Add record to SQL") -Verbose + $SqlQuery = "INSERT INTO [$SnapshotTable] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('$Name', '$StartDateTimeSql', '$RequestedBy', $DurationHours, 'Requested', '$EndDateTimeSql','$Email','$PSUJobId');SELECT SCOPE_IDENTITY();" + Write-Verbose -Message $SqlQuery -Verbose + $SnapshotId = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose).Column1 + Write-Verbose -Message ("Snapshot ID is $SnapshotId") -Verbose + + Write-Verbose -Message "Get SQL record" -Verbose + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE ID='$SnapshotId'" + Write-Verbose -Message $SqlQuery -Verbose + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message $SqlRecord -Verbose + + Write-Verbose -Message ("Determine description metadata") -Verbose + $MetadataObj = @{ + Id = [int]$SnapshotId; + Taken = $StartDateTime; + Expire = $EndDateTime; + RequestedBy = $RequestedBy; + DurationHours = $DurationHours; + PSUJobIdRequest = $PSUJobId; + } + + Write-Verbose -Message ("Create VM Scheduled Task for Snapshot " + $SnapshotId) -Verbose + + $NewITDVMwareVMSnapshotTaskParams = @{ + VMName = $name; + Name = ("AutoSnap_" + $SnapshotId) + Description = $MetadataObj | ConvertTo-Json + DateTime = $StartDateTime; + } + + switch ($PSBoundParameters.Keys) { + Email { + $NewITDVMwareVMSnapshotTaskParams.Email = $Email + } + } + + try { + New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams -Verbose -ErrorAction Stop + Write-Verbose -Message ("Setting SQL status to Scheduled") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Scheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + + Write-Verbose -Message ($NewITDVMwareVMSnapshotTaskParams.Name + " has been scheduled.") -Verbose + } + catch { + Write-Verbose -Message "ObjectNotFound Error" -Verbose + switch ($Error[0].Exception.ErrorCategory) { + 'ObjectNotFound' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed, ObjectNotFound.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-VMNotFound' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + 'Default' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-GenericError' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Write-Error -Message $Error[0] + } +} + +Disconnect-ITDvCenter + +# Write-Verbose -Message ("If scheduled task is created successfully, create SNow CHG for this, using scheduled StartDateTime... work TBD") -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotExpiredIncident.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotExpiredIncident.ps1 new file mode 100644 index 0000000..a9c87ba --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotExpiredIncident.ps1 @@ -0,0 +1,59 @@ +## TO-DO: update SQL status to Expired-Alerted when a ticket is created, so duplicate tickets are not generated + +[CmdletBinding()] +param ( + [string] + $VMName, + + [int] + $Id, # ?? + + [switch] + $WhatIf +) + +Write-Verbose -Message "Connect to vCenter and ServiceNow" +New-ITDServiceNowSession -Environment Production -Credential $Secret:SnowVMCred +Connect-ITDvCenter -Credential $Secret:svcitdiaasauto + +# find all VMs, with VMName if entered +If ($PSBoundParameters.ContainsKey('VMName')) { + Write-Verbose -Message "VMname parameter found $VMName" -Verbose + $VMs = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} +Else { + Write-Verbose -Message "VMname parameter not found" -Verbose + $VMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} + +# find expired snapshots of the VMs +If ($PSBoundParameters.ContainsKey('Id')) { + + Write-Verbose -Message "ID parameter found $Id" -Verbose + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -Like "AutoSnap_$Id*" +} +Else { + Write-Verbose -Message "ID parameter not found" -Verbose + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -Like "AutoSnap_*" +} + +ForEach ($Snapshot in $AllSnapshots) { + $SnapshotObj = $Snapshot.Description | ConvertFrom-Json + If ( $SnapshotObj.Expire -lt (Get-Date).AddHours(-24) ) { + $NewITDServiceNowIncidentParams = @{ + CallerUsername = 'svcvmwareadm'; + ShortDescription = ("VMware Snapshot #" + $SnapshotObj.Id + " cleanup failure."); + Description = ("VMware Snapshot #" + $SnapshotObj.ID + " cleanup failure. Snapshot expired more than 24 hours ago, but it still exists."); + Impact = 3; + Urgency = 3; + Category = 'Systems Platforms - Systems'; + Subcategory = 'VMware'; + AssignmentGroup = 'NDIT-Computer Systems Windows'; + } + New-ITDServiceNowIncident @NewITDServiceNowIncidentParams + } +} + + + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 new file mode 100644 index 0000000..1bc1377 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/New-ITDVMwareVMSnapshotTask.ps1 @@ -0,0 +1,133 @@ +<##### +.SYNOPSIS + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.DESCRIPTION + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.NOTES + +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0017146 +#> + +[CmdletBinding()] +param ( + [Parameter( + Mandatory = $true, + HelpMessage = "The VMware virtual machine name. This is most commonly the FQDN. You can verify the virtual machine name by logging into vCenter. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back." + )] + [string[]] + $VMName = $null, + + [Parameter(Mandatory = $true, + HelpMessage = "The DateTime you want the snapshot to occur.")] + [datetime] + $DateTime = (Get-Date), + + [Parameter(Mandatory = $true, + HelpMessage = "How many hours the snapshot will exist. The snapshot will be automatically deleted after the duration. Maximum value is 72 hours.")] + [ValidateRange(1, 72)] + [int] + $DurationHours = 4, + + [Parameter(HelpMessage = "Email address that you want vCenter to notify when the snapshot is taken. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $Email = $null +) + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +$RequestedBy = $UAJob.Identity.Name # user that started the job +$PSUJobId = $UAJob.Id + +$StartDateTime = $DateTime +$EndDateTime = $StartDateTime.AddHours($DurationHours) +Write-Verbose -Message ("UAJob.ComputerName = " + $UAJob.ComputerName) -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +$StartDateTimeSql = $StartDateTime.ToString('yyyy/MM/dd HH:mm:ss') +$EndDateTimeSql = $EndDateTime.ToString('yyyy/MM/dd HH:mm:ss') + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr +Write-Verbose -Message "After Connect vCenter" -Verbose + + +ForEach ($name in $VMName) { + Write-Verbose -Message ("Add record to SQL") -Verbose + $SqlQuery = "INSERT INTO [$SnapshotTable] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('$Name', '$StartDateTimeSql', '$RequestedBy', $DurationHours, 'Requested', '$EndDateTimeSql','$Email','$PSUJobId');SELECT SCOPE_IDENTITY();" + Write-Verbose -Message $SqlQuery -Verbose + $SnapshotId = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose).Column1 + Write-Verbose -Message ("Snapshot ID is $SnapshotId") -Verbose + + Write-Verbose -Message "Get SQL record" -Verbose + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE ID='$SnapshotId'" + Write-Verbose -Message $SqlQuery -Verbose + $SqlRecord = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message $SqlRecord -Verbose + + Write-Verbose -Message ("Determine description metadata") -Verbose + $MetadataObj = @{ + Id = [int]$SnapshotId; + Taken = $StartDateTime; + Expire = $EndDateTime; + RequestedBy = $RequestedBy; + DurationHours = $DurationHours; + PSUJobIdRequest = $PSUJobId; + } + + Write-Verbose -Message ("Create VM Scheduled Task for Snapshot " + $SnapshotId) -Verbose + + $NewITDVMwareVMSnapshotTaskParams = @{ + VMName = $name; + Name = ("AutoSnap_" + $SnapshotId) + Description = $MetadataObj | ConvertTo-Json + DateTime = $StartDateTime; + } + + switch ($PSBoundParameters.Keys) { + Email { + $NewITDVMwareVMSnapshotTaskParams.Email = $Email + } + } + + try { + New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams -Verbose -ErrorAction Stop + Write-Verbose -Message ("Setting SQL status to Scheduled") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Scheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + + Write-Verbose -Message ($NewITDVMwareVMSnapshotTaskParams.Name + " has been scheduled.") -Verbose + } + catch { + Write-Verbose -Message "ObjectNotFound Error" -Verbose + switch ($Error[0].Exception.ErrorCategory) { + 'ObjectNotFound' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed, ObjectNotFound.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-VMNotFound' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + 'Default' { + # update SQL with error + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has failed.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-GenericError' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Write-Error -Message $Error[0] + } +} + +Disconnect-ITDvCenter + +# Write-Verbose -Message ("If scheduled task is created successfully, create SNow CHG for this, using scheduled StartDateTime... work TBD") -Verbose diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 new file mode 100644 index 0000000..fe4f523 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotExpired.ps1 @@ -0,0 +1,99 @@ +[CmdletBinding()] +param ( + [string] + $VMName, + + [int] + $Id, + + [switch] + $WhatIf +) + +$PSUJobId = $UAJob.Id + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose + +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +# find all VMs, with VMName if entered +If ($PSBoundParameters.ContainsKey('VMName')) { + Write-Verbose -Message "VMName parameter found $VMName" -Verbose + $VMs = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} +Else { + $VMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +} + +# find expired snapshots of the VMs +If ($PSBoundParameters.ContainsKey('Id')) { + Write-Verbose -Message "ID parameter found $Id" -Verbose + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -EQ "AutoSnap_$Id" +} +Else { + $AllSnapshots = $VMs | Get-Snapshot | Where-Object Name -Like "AutoSnap_2*" ##### Remove the '2' after SharePoint snapshots are all deleted +} + +ForEach ($Snapshot in $AllSnapshots) { + Write-Verbose -Message ("Start Snapshot " + $Snapshot.Description) -Verbose + $SnapshotObj = $null + + $SnapshotObj = $Snapshot.Description | ConvertFrom-Json + If ($null -ne $SnapshotObj -and $SnapshotObj.Expire -lt (Get-Date)) { + # remove snapshot if expired + If ($WhatIf) { + Write-Verbose -Message ("What if: Performing the operation Remove-Snapshot on Snapshot " + $Snapshot.Name) -Verbose + } + Else { + Write-Verbose -Message ("VMName: " + $Snapshot.VM.Name + " / Snapshot ID: " + $SnapshotObj.Id + " -- attempting removal") -Verbose + + # update SQL status to "Delete-Attempted" + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Delete-AutoAttempt', PSUJobIdDelete = '$PSUJobId' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + + # Remove Snapshot + $Snapshot | Remove-Snapshot -Confirm:$false -Verbose + + # confirm snapshot is truly gone, then update sql with results + If (Get-VM -Name $Snapshot.VM.Name | Get-Snapshot -Id $SnapshotObj.Id -ErrorAction SilentlyContinue) { + $RemoveStatus = $false + } + Else { + # snapshot does not exist + $RemoveStatus = $true + } + + # update SQL + switch ($RemoveStatus) { + $true { + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-AutoSuccess' WHERE ID = " + $Snapshot.Name.split('_')[1]) + } + $false { + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-AutoFailure' WHERE ID = " + $Snapshot.Name.split('_')[1]) + } + } + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + # do nothing + Write-Verbose -Message ("VMName: " + $Snapshot.VM.Name + " / Snapshot ID: " + $SnapshotObj.Id + " has not expired.") -Verbose + } +} + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotTaskOrphan.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotTaskOrphan.ps1 new file mode 100644 index 0000000..c65d8e4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Remove-ITDVMwareVMSnapshotTaskOrphan.ps1 @@ -0,0 +1,3 @@ +## To-do: Remove vCenter scheduled tasks for snapshots that are more than 30 days old. + +# still need to do this \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-ScriptPerms3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-ScriptPerms3.ps1 new file mode 100644 index 0000000..e3f1a12 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-ScriptPerms3.ps1 @@ -0,0 +1 @@ +#code goes here \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-vCenterConnection.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-vCenterConnection.ps1 new file mode 100644 index 0000000..60e14ca --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Test-vCenterConnection.ps1 @@ -0,0 +1,8 @@ +# It all starts with a single line of powershell code. TEST TEST TEST moar TEST +Write-Verbose -Message "Start Test-vCenterConnection.ps1" -Verbose +Write-Host $Secret:svcitdiaasauto.username +Connect-ITDvCenter -Credential $Secret:svcitdiaasauto +Get-Datacenter +Disconnect-ITDvCenter +Write-Verbose -Message "End Test-vCenterConnection.ps1" -Verbose +# \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 new file mode 100644 index 0000000..a54cded --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 @@ -0,0 +1,203 @@ +[CmdletBinding()] +param ( + [int] + $Id +) + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmsnapmgr + +Write-Verbose -Message "Prepare variables / SQL connection based on PSU server" -Verbose +switch($UAJob.ComputerName){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + +# get list of All vCenter Scheduled Tasks +$si = Get-View ServiceInstance +$scheduledTaskManager = Get-View $Si.Content.ScheduledTaskManager +Write-Verbose -Message ("Gathering all scheduled tasks with AutoSnap in the task name, this will take some time") +$AllScheduledTasks = Get-View -Id $scheduledTaskManager.ScheduledTask | Where-Object { $_.Info.Name -like "AutoSnap*" } + +Write-Verbose -Message "Get SQL records with status of Scheduled" -Verbose +# get list of Scheduled from database +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Scheduled'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Scheduled status") -Verbose +Write-Verbose -Message "Start Scheduled > Taken Loops" +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + Write-Verbose -Message ("Setting SQL status to Taken") -Verbose + # if status has changed from requested to taken, update database status field + $TakenDateTimeSql = ($Snapshot.Description | ConvertFrom-Json).Taken.ToString('yyyy/MM/dd HH:mm:ss') + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Taken', TakenDateTime = '" + $TakenDateTimeSql + "' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + If ($SqlRecord.DateTime -lt (Get-Date)) { + Write-Error -Message ("AutoSnap_" + $SqlRecord.Id + " not found, and its requested datetime has passed") -Verbose + # Update SQL record to status Failed-ScheduledNotTaken + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-ScheduledNotTaken' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose +} + +Write-Verbose -Message "End Scheduled > Taken Loops" +$SqlRecord = $null +$SqlRecords = $null +$SqlQueryUpdate = $null + +# get list of taken from database +Write-Verbose -Message "Start Taken > Expire Loops" +Write-Verbose -Message "Get SQL records with status of Taken" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Taken'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Taken SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Taken status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + # if expired datetime is in the past, set status to expired + If ( ($Snapshot.Description | ConvertFrom-Json).Expire -lt (Get-Date)) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " has expired.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Expired' WHERE ID = " + $Snapshot.Name.split('_')[1]) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-Manual' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose + $SqlRecord = $null + $SqlRecords = $null + $SqlQueryUpdate = $null +} + +# get list of Expired from SQL database + +Write-Verbose -Message "Start Expired > Removed Loops" +Write-Verbose -Message "Get SQL records with status of Expired" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Expired'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Expired SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Expired status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + $Snapshot = $null + + Write-Verbose -Message ("Start AutoSnap_" + $SqlRecord.Id) -Verbose + $Snapshot = Get-VM -Name $SqlRecord.VMName | Get-Snapshot -Name ("AutoSnap_" + $SqlRecord.ID) -ErrorAction SilentlyContinue + + If ($Snapshot) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " found. Taken: " + ($Snapshot.Description | ConvertFrom-Json).Taken + ". Expire: " + ($Snapshot.Description | ConvertFrom-Json).Expire) -Verbose + # if expired datetime is in the past, set status to expired + If ( ($Snapshot.Description | ConvertFrom-Json).Expire -lt (Get-Date)) { + Write-Verbose -Message ("Snapshot " + $Snapshot.Name + " is expired. Will be removed at next Removal run") -Verbose + #$SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Expired' WHERE ID = " + $Snapshot.Name.split('_')[1]) + #Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + } + Else { + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " not found.") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Deleted-Manual' WHERE ID = " + $SqlRecord.Id) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Write-Verbose -Message ("End AutoSnap_" + $SqlRecord.Id) -Verbose + $SqlRecord = $null + $SqlRecords = $null + $SqlQueryUpdate = $null +} + + +# get list of requested from SQL database +Write-Verbose -Message "Start Requested > Scheduled Loops" +Write-Verbose -Message "Get SQL records with status of Requested" -Verbose +$SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[$SnapshotTable] WHERE Status = 'Requested'" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +switch ($PSBoundParameters.Keys) { + Id { + Write-Verbose -Message "Narrowing results to Id parameter value of $Id" -Verbose + $SqlRecords = $SqlRecords | Where-Object Id -EQ "$Id" + } +} + +# check status of all Requested SQLRecords +Write-Verbose -Message ("Found " + @($SqlRecords).count + " snapshots with Requested status") -Verbose +ForEach ($SqlRecord in @($SqlRecords) ) { + # does the scheduled tasks exist? + If ($AllScheduledTasks | Where-Object { $_.Info.Name -eq ("AutoSnap_" + $SqlRecord.Id + '_' + $SqlRecord.VMName) }) { + # yes - update SQL status to Scheduled + Write-Verbose -Message ("AutoSnap_" + $SqlRecord.Id + " vCenter scheduled task exists.") -Verbose + Write-Verbose -Message ("Setting SQL status to Scheduled") -Verbose + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Scheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + # no + # has date/time passed? (10 minute buffer) + If ($SqlRecord.DateTime -lt (Get-Date).AddMinutes(-10)) { + # yes - set SQL status to Failed-RequestedNotScheduled + Write-Warning -Message ("AutoSnap_" + $SqlRecord.Id + " was not scheduled before its datetime.") + $SqlQueryUpdate = ("UPDATE [$SnapshotTable] SET Status = 'Failed-RequestedNotScheduled' WHERE ID = " + $SqlRecord.ID) + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQueryUpdate -Credential $Secret:sql_itdpsu1 -Verbose + } + Else { + # no ??? + } + Write-Error -Message ("AutoSnap_" + $SqlRecord.Id + " scheduled task does not exist.") + } +} +Write-Verbose -Message "End Requested > Scheduled Loops" +$SqlRecord = $null +$SqlRecords = $null +$SqlQueryUpdate = $null + +Disconnect-ITDvCenter diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 new file mode 100644 index 0000000..9713723 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Add-ITDServerBuildRitmToSql.ps1 @@ -0,0 +1,90 @@ +Param( + [string] + $Ritm, + + [string] + $ComputerName +) +# $cat_item_sys_id = 'c64e27af47244610b7853238436d435d' +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Prep variable and SQL connection" -Verbose +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = "ServiceNow_RitmDump_ServerBuildRequestV1" + +$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm -IncludeCustomVariable -IncludeVariableSet + +ForEach ($Ritm in $AllRitms) { + Write-Verbose ("Start " + $Ritm.number) -Verbose + # get all variable set rows + $VariableSet = (Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -IncludeVariableSet).VariableSet + ForEach ($VSet in $VariableSet) { + Write-Verbose -Message ("Start " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # figure out values + $RitmNum = $Ritm.number.value + $RitmSysId = $Ritm.sys_id.value + $opened_at = $Ritm.opened_at.display_value + $requested_for = $Ritm.requested_for.display_value + $request_type = $Ritm.CustomVariable.request_type.value + $environment = $Ritm.CustomVariable.environment.value + $host_name_ref = $VSet.host_name_ref + $host_name = If ($VSet.host_name_ref) { + (Get-ITDServiceNowRecord -Table cmdb_ci -SysId $VSet.host_name_ref).Name.display_value + } + Else { + $VSet.host_name + } + $server_type = $VSet.server_type + $operating_system = $VSet.operating_system + $target_os_version_linux = $VSet.target_os_version_linux + $target_os_version_windows = $VSet.target_os_version_windows + $target_platform = $VSet.target_platform + $processors = $VSet.processors + $memory_gb = $VSet.memory_gb + $cidr_block_sys_id = $VSet.cidr_block + $cidr_block = (Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId $cidr_block_sys_id).subnet.display_value + $vlan_id = $VSet.vlan_id + $data_center = $VSet.data_center + $licensing_restrictions = $VSet.licensing_restrictions + $application_info_sys_id = $VSet.application_info + $application_info = (Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId $application_info_sys_id).name.display_value + $support_hours = $VSet.support_hours + $dr_protection = $VSet.dr_protection + $startup_priority = $VSet.startup_priority + $disk_1_os = $VSet.disk_1_os + $disk_2_swap_disk = $VSet.disk_2_swap_disk + $disk_3 = $VSet.disk_3 + $disk_4 = $VSet.disk_4 + $disk_5 = $VSet.disk_5 + $disk_6 = $VSet.disk_6 + $disk_7 = $VSet.disk_7 + $disk_8 = $VSet.disk_8 + $disk_9 = $VSet.disk_9 + $disk_10 = $VSet.disk_10 + $disk_11 = $VSet.disk_11 + $disk_12 = $VSet.disk_12 + $disk_13 = $VSet.disk_13 + $disk_14 = $VSet.disk_14 + $disk_15 = $VSet.disk_15 + $disk_16 = $VSet.disk_16 + $special_instructions = $Ritm.CustomVariable.special_instructions.value + $customer_request = $Ritm.CustomVariable.customer_request.value + $additional_comments = $Ritm.CustomVariable.additional_comments.value + + If ($host_name -eq $ComputerName) { + Write-Verbose -Message ("Add to SQL " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # add record to SQL + $SqlQuery = "INSERT INTO [$Table] ( + RitmNum, RitmSysId, opened_at,requested_for,request_type,environment,host_name_ref,host_name,server_type,operating_system,target_os_version_linux,target_os_version_windows,target_platform,processors,memory_gb,cidr_block_sys_id,cidr_block,vlan_id,data_center,licensing_restrictions,application_info_sys_id,application_info,support_hours,dr_protection,startup_priority,disk_1_os,disk_2_swap_disk,disk_3,disk_4,disk_5,disk_6,disk_7,disk_8,disk_9,disk_10,disk_11,disk_12,disk_13,disk_14,disk_15,disk_16,special_instructions,customer_request,additional_comments) Values ( + '$RitmNum','$RitmSysId','$opened_at','$requested_for','$request_type','$environment','$host_name_ref','$host_name','$server_type','$operating_system','$target_os_version_linux','$target_os_version_windows','$target_platform','$processors','$memory_gb','$cidr_block_sys_id','$cidr_block','$vlan_id','$data_center','$licensing_restrictions','$application_info_sys_id','$application_info','$support_hours','$dr_protection','$startup_priority','$disk_1_os','$disk_2_swap_disk','$disk_3','$disk_4','$disk_5','$disk_6','$disk_7','$disk_8','$disk_9','$disk_10','$disk_11','$disk_12','$disk_13','$disk_14','$disk_15','$disk_16','$special_instructions','$customer_request','$additional_comments' + ) + " + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message $SqlQuery -Verbose + } + Write-Verbose -Message ("End " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + } + Write-Verbose ("End " + $Ritm.number) -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Approve-ITDVMNewBuild_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Approve-ITDVMNewBuild_script.ps1 new file mode 100644 index 0000000..2aac0b0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Approve-ITDVMNewBuild_script.ps1 @@ -0,0 +1,85 @@ +Param( + [string] + $SCTaskNum +) + +New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred +Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + +$Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-like', 'Windows Guest OS complete. Hardware team review.'), '-and', @('state', '-eq', '2') # 2 = 'work in progress' +$OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object Number -EQ $SCTaskNum +} + +Write-Verbose -Message ("OpenTasks found: " + $OpenTasks.count) -Verbose +ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message $OpenTasks.Number -Verbose +} + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + Write-Verbose -Message "Start $SCTasknum" -Verbose + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $shortdescription = $SCTask.short_description + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable -WarningAction SilentlyContinue + + switch (($Ritm.CustomVariable | Where-Object Name -EQ target_platform).Value) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + $FormFQDN = ($RITM.CustomVariable | Where-Object Name -EQ "host_name").value + $FormHostName = $FormFQDN.split('.')[0] + + $Ci = Get-ServiceNowRecord -Table cmdb_ci -Filter @('name', '-eq', $FormHostName) + + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + switch ($target_platform) { + { $_ -like "*VMware*" } { + Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + Write-Verbose -Message ("$FormFQDN is a VMware VM. Determine if SRM was requested.") -Verbose + $hardware_platform = "VMware"; + $hardware_type = 'Virtual Machine' + + If ( ($Ritm.CustomVariable | Where-Object Name -EQ 'dr_protection').Value -eq 'No DR') { + Write-Verbose -Message ("$FormFQDN dr_protection equals 'No DR'") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum -CloseTask -Verbose + } + Else { + Write-Verbose -Message ("$FormFQDN dr_protection is requested") -Verbose + Write-Warning -Message ("SRM is requested, task will not auto close. -- ZM") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + Disconnect-ITDvCenter + } + { $_ -like "*Microsoft Virtual Machine*" } { + Write-Verbose -Message ("$FormFQDN is an Azure VM. DR is not an option, proceed.") -Verbose + $hardware_platform = "Azure"; + $hardware_type = 'Virtual Machine' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + #Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + { $_ -like "*HP*" } { + Write-Verbose -Message ("$FormFQDN is an HPE device.") -Verbose + $hardware_platform = 'HPE'; + $hardware_type = 'Physical' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + } + default { + $hardware_platform = 'Other' + Write-Warning -Message ("Ci found, but unavailable to determine hardware platform.") + } + } + +} + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 new file mode 100644 index 0000000..a6b40fc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Move-ITDVMwareVMToAppNameFolder_Auto.ps1 @@ -0,0 +1,46 @@ +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] + [string[]] + $VMName, + + [Parameter(Mandatory = $true, ParameterSetName = 'NewBuilds')] + [switch] + $NewBuilds, + + [Parameter(Mandatory = $true, ParameterSetName = 'All')] + [switch] + $All +) + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +switch ($PSCmdlet.ParameterSetName) { + 'VMName' { + Write-Verbose -Message "Parameter Set VMName" -Verbose + $VMs = Get-VM -Name $VMName + } + 'NewBuilds' { + Write-Verbose -Message "Parameter Set NewBuilds" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM + } + 'All' { + Write-Verbose -Message "Parameter Set All" -Verbose + $VMs = Get-VM | Where-Object CreateDate -lt ((Get-Date).AddDays(-2)) + } +} + +ForEach($VM in $VMs){ + try{ + Write-Verbose -Message ("Start " + $VM.Name) -Verbose + Get-VM -Name $VM.Name | Select Uid + Move-ITDVMwareVMToAppNameFolder -VMName $VM.Name -ErrorAction Stop -Verbose + } + catch { + $error[0] + } +} + + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/New-ITDVMwareSharePointVMRecordFromRITM.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/New-ITDVMwareSharePointVMRecordFromRITM.ps1 new file mode 100644 index 0000000..502a3d3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/New-ITDVMwareSharePointVMRecordFromRITM.ps1 @@ -0,0 +1,28 @@ +Param ( + [string] + $Fqdn, + + [string] + $RitmNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum -IncludeVariableSet -IncludeCustomVariable +$Row = $Ritm.VariableSet | Where-Object host_name -eq $Fqdn + +$NewITDVMwareSharePointVMRecordParams = @{ + HostName = $Fqdn; + LicensingRestrictions = $Row.licensing_restrictions; + DataCenter = $Row.data_center; + Environment = $Ritm.CustomVariable.environment.value; + StartupPriority = $Row.startup_priority; + OperatingSystem = $Row.operating_system; + DR_Protection = $Row.dr_protection; + CPU = $Row.processors; + MemoryGB = $Row.memory_gb; + Disk1 = $Row.disk_1_os; + Disk2 = $Row.disk_2_swap_disk; + Disk3 = $Row.disk_3; +} +New-ITDVMwareSharePointVMRecord @NewITDVMwareSharePointVMRecordParams \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 new file mode 100644 index 0000000..e456f97 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Set-ITDVMwareVMTagFromCmdb.ps1 @@ -0,0 +1,58 @@ +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] + [string[]] + $VMName, + + [Parameter(Mandatory = $true, ParameterSetName = 'NewBuilds')] + [switch] + $NewBuilds, + + [Parameter(Mandatory = $true, ParameterSetName = 'All')] + [switch] + $All +) + +Write-Verbose -Message "Connect to ServiceNow" -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +<#switch ($PSBoundParameters.ContainsKey('VMName')) { + $true { + $VMs = Get-VM -Name $VMName + } + $false { + Write-Verbose -Message "VMName parameter not provided, working on new builds only" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + } +}#> + +switch ($PSCmdlet.ParameterSetName) { + 'VMName' { + Write-Verbose -Message "Parameter Set VMName" -Verbose + $VMs = Get-VM -Name $VMName + } + 'NewBuilds' { + Write-Verbose -Message "Parameter Set NewBuilds" -Verbose + $VMs = Get-Folder -Name "_New Builds" | Get-VM + } + 'All' { + Write-Verbose -Message "Parameter Set All" -Verbose + $VMs = Get-VM + } +} + +ForEach($VM in $VMs){ + try{ + Write-Verbose -Message ("Start " + $VM.Name) -Verbose + Set-ITDVMwareVMTagFromCmdb -VMName $VM.Name -ErrorAction Stop -Verbose + } + catch { + $error[0] + } +} + + +Write-Verbose -Message "Disconnect from vCenter" -Verbose +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 new file mode 100644 index 0000000..6a3edcf --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDServerBuildRITMs.ps1 @@ -0,0 +1,158 @@ +# loop through them, create sql record + +# $cat_item_sys_id = 'c64e27af47244610b7853238436d435d' +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Prep variable and SQL connection" -Verbose +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = "ServiceNow_RitmDump_ServerBuildRequestV1" + +# get most recent RITM from SQL, get the opened_at value +$SqlQuery = "SELECT [RitmNum],[RitmSysId],[opened_at] FROM [$Database].[dbo].[$Table]" +$SqlExistingRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + +$NewestRecord = ($SqlExistingRecords | Sort-Object -Descending opened_at) | select -First 1 +$DateYMDFilter = ($NewestRecord.opened_at | Get-Date -UFormat "%Y-%m-%d") +$DateHMSFilter = ($NewestRecord.opened_at | Get-Date -UFormat "%H:%M:%S") + +#$Filter = "cat_item=c64e27af47244610b7853238436d435d^opened_at>javascript:gs.dateGenerate('2024-07-30','23:59:59')" + +#$Filter = "cat_item=c64e27af47244610b7853238436d435d" +$Filter = "cat_item=c64e27af47244610b7853238436d435d^opened_at>javascript:gs.dateGenerate('$DateYMDFilter','$DateHMSFilter')" +Write-Verbose -Message ("Filter is " + $Filter) -Verbose + +# retrieve list of RITMs created since $opened_at (>opened_at) +Write-Verbose -Message "Retrieve list of RITMs created since last update" -Verbose +#$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter -IncludeTotalCount -IncludeCustomVariable | Sort-Object Number +$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Filter $Filter -IncludeTotalCount -IncludeCustomVariable | Sort-Object Number +#$AllRitms = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number 'RITM0262097' -IncludeCustomVariable +Write-Verbose -Message ("RITMs found: " + @($AllRitms).count) -Verbose + + +ForEach ($Ritm in $AllRitms) { + Write-Verbose ("Start " + $Ritm.number) -Verbose + # get all variable set rows + $VariableSet = (Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -IncludeVariableSet).VariableSet + ForEach ($VSet in $VariableSet) { + Write-Verbose -Message ("Start " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # figure out values + $RitmNum = $Ritm.number.value + $RitmSysId = $Ritm.sys_id.value + $opened_at = $Ritm.opened_at.display_value + $requested_for = $Ritm.requested_for.display_value + $request_type = $Ritm.CustomVariable.request_type.value + $environment = $Ritm.CustomVariable.environment.value + $host_name_ref = $VSet.host_name_ref + $host_name = If ($VSet.host_name_ref) { + (Get-ITDServiceNowRecord -Table cmdb_ci -SysId $VSet.host_name_ref).Name.display_value + } + Else { + $VSet.host_name + } + $server_type = $VSet.server_type + $operating_system = $VSet.operating_system + $target_os_version_linux = $VSet.target_os_version_linux + $target_os_version_windows = $VSet.target_os_version_windows + $target_platform = $VSet.target_platform + $processors = $VSet.processors + $memory_gb = $VSet.memory_gb + $cidr_block_sys_id = $VSet.cidr_block + $cidr_block = (Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -SysId $cidr_block_sys_id).subnet.display_value + $vlan_id = $VSet.vlan_id + $data_center = $VSet.data_center + $licensing_restrictions = $VSet.licensing_restrictions + $application_info_sys_id = $VSet.application_info + $application_info = (Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -SysId $application_info_sys_id).name.display_value + $support_hours = $VSet.support_hours + $dr_protection = $VSet.dr_protection + $startup_priority = $VSet.startup_priority + $disk_1_os = $VSet.disk_1_os + $disk_2_swap_disk = $VSet.disk_2_swap_disk + $disk_3 = $VSet.disk_3 + $disk_4 = $VSet.disk_4 + $disk_5 = $VSet.disk_5 + $disk_6 = $VSet.disk_6 + $disk_7 = $VSet.disk_7 + $disk_8 = $VSet.disk_8 + $disk_9 = $VSet.disk_9 + $disk_10 = $VSet.disk_10 + $disk_11 = $VSet.disk_11 + $disk_12 = $VSet.disk_12 + $disk_13 = $VSet.disk_13 + $disk_14 = $VSet.disk_14 + $disk_15 = $VSet.disk_15 + $disk_16 = $VSet.disk_16 + $special_instructions = $Ritm.CustomVariable.special_instructions.value + $customer_request = $Ritm.CustomVariable.customer_request.value + $additional_comments = $Ritm.CustomVariable.additional_comments.value + + Write-Verbose -Message ("Add to SQL " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + # add record to SQL + $SqlQuery = "INSERT INTO [$Table] ( + RitmNum, RitmSysId, opened_at,requested_for,request_type,environment,host_name_ref,host_name,server_type,operating_system,target_os_version_linux,target_os_version_windows,target_platform,processors,memory_gb,cidr_block_sys_id,cidr_block,vlan_id,data_center,licensing_restrictions,application_info_sys_id,application_info,support_hours,dr_protection,startup_priority,disk_1_os,disk_2_swap_disk,disk_3,disk_4,disk_5,disk_6,disk_7,disk_8,disk_9,disk_10,disk_11,disk_12,disk_13,disk_14,disk_15,disk_16,special_instructions,customer_request,additional_comments) Values ( + '$RitmNum','$RitmSysId','$opened_at','$requested_for','$request_type','$environment','$host_name_ref','$host_name','$server_type','$operating_system','$target_os_version_linux','$target_os_version_windows','$target_platform','$processors','$memory_gb','$cidr_block_sys_id','$cidr_block','$vlan_id','$data_center','$licensing_restrictions','$application_info_sys_id','$application_info','$support_hours','$dr_protection','$startup_priority','$disk_1_os','$disk_2_swap_disk','$disk_3','$disk_4','$disk_5','$disk_6','$disk_7','$disk_8','$disk_9','$disk_10','$disk_11','$disk_12','$disk_13','$disk_14','$disk_15','$disk_16','$special_instructions','$customer_request','$additional_comments' + ) + " + + Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + Write-Verbose -Message ("End " + $VSet.host_name + ' *** ' + $VSet.host_name_ref) + } + Write-Verbose ("End " + $Ritm.number) -Verbose +} + +<# scratch +Write-Verbose -Message ("Add record to SQL") -Verbose +$SqlQuery = "INSERT INTO [$SnapshotTable] (VMName, DateTime, RequestedBy, DurationHours,Status,ExpireDateTime,NotifyEmail,PSUJobIdRequest) Values ('$Name', '$StartDateTimeSql', '$RequestedBy', $DurationHours, 'Requested', '$EndDateTimeSql','$Email','$PSUJobId');SELECT SCOPE_IDENTITY();" +#Write-Verbose -Message $SqlQuery -Verbose +$SnapshotId = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:itdpsu1 -Verbose).Column1 + + + + +select TOP (1000) [RitmNum] +, [RitmSysId] +, [opened_at] +, [requested_for] +, [request_type] +, [environment] +, [host_name_ref] +, [host_name] +, [server_type] +, [operating_system] +, [target_os_version_linux] +, [target_os_version_windows] +, [target_platform] +, [processors] +, [memory_gb] +, [cidr_block_sys_id] +, [cidr_block] +, [vlan_id] +, [data_center] +, [licensing_restrictions] +, [application_info_sys_id] +, [application_info] +, [support_hours] +, [dr_protection] +, [startup_priority] +, [disk_1_os] +, [disk_2_swap_disk] +, [disk_3] +, [disk_4] +, [disk_5] +, [disk_6] +, [disk_7] +, [disk_8] +, [disk_9] +, [disk_10] +, [disk_11] +, [disk_12] +, [disk_13] +, [disk_14] +, [disk_15] +, [disk_16] +, [special_instructions] +, [customer_request] +, [additional_comments] +FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1] +#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 new file mode 100644 index 0000000..1376858 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint.ps1 @@ -0,0 +1,25 @@ +Param( + [string] + $VMName, + + [switch] + $SRMImplemented +) + +Write-Verbose "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro +Write-Verbose "Start Sync" -Verbose + +switch ($PSBoundParameters.Keys){ + 'VMName' { $SyncITDVMwareVMMetadataToSharePointParams += @{VMName = $VMName} } + 'SRMImplemented' { $SyncITDVMwareVMMetadataToSharePointParams += @{SRMImplemented = $SRMImplemented} } +} + +Write-Host $SyncITDVMwareVMMetadataToSharePointParams + +Sync-ITDVMwareVMMetadataToSharePoint @SyncITDVMwareVMMetadataToSharePointParams -Verbose +#Write-Output $VMName +Write-Verbose "End Sync" + +Write-Verbose "Disconnect vCenter" +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint_script.ps1 new file mode 100644 index 0000000..38dcce6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMMetadataToSharePoint_script.ps1 @@ -0,0 +1,15 @@ +Param( + [string] + $VMName +) + +Write-Verbose "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro + +Write-Verbose "Start Sync" -Verbose +Sync-ITDVMwareVMMetadataToSharePoint -VMName $VMName +#Write-Output $VMName +Write-Verbose "End Sync" + +Write-Verbose "Disconnect vCenter" +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 new file mode 100644 index 0000000..ef2625d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Sync-ITDVMwareVMTagsFromCmdb.ps1 @@ -0,0 +1,10 @@ +Write-Verbose -Message "Connect to ServiceNow" -Verbose +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +Write-Verbose -Message "Connect to vCenter" -Verbose +Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + +Write-Verbose -Message "Execute Sync-ITDVMareVMTagsFromCmdb" -Verbose +Sync-ITDVMwareVMTagsFromCmdb -Verbose + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSNowVMTaskDescription_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSNowVMTaskDescription_script.ps1 new file mode 100644 index 0000000..90323ae --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSNowVMTaskDescription_script.ps1 @@ -0,0 +1,2 @@ +New-ITDServiceNowSession -Environment Production -Credential $Secret:SNowVMCred +Update-ITDSNowVMTaskDescription -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 new file mode 100644 index 0000000..a6691e9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Infra-VMware.VirtualMachine/Update-ITDSnowVMTaskDescription.ps1 @@ -0,0 +1,2 @@ +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred +Update-ITDSNowVMTaskDescription -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Shared-Powerschool/20240805dontest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Shared-Powerschool/20240805dontest.ps1 new file mode 100644 index 0000000..e3f1a12 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/Shared-Powerschool/20240805dontest.ps1 @@ -0,0 +1 @@ +#code goes here \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Get-HelloWorld.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Get-HelloWorld.ps1 new file mode 100644 index 0000000..ca5c618 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Get-HelloWorld.ps1 @@ -0,0 +1,6 @@ +Param( + [string] + $SCTaskNum = "World" +) + +Write-Host "Hello, $WorldName!" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-ITDDummyFile.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-ITDDummyFile.ps1 new file mode 100644 index 0000000..0364263 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-ITDDummyFile.ps1 @@ -0,0 +1,4 @@ +# It all starts with a single line of powershell code. +$DateTime = Get-Date -UFormat "%Y%m%d%H%M%S" +New-Item -Name "Dummy$DateTime" -Path "C:\ITD\DummyFiles\" +Start-Sleep -Seconds 360 \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-TestNestedInvoke.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-TestNestedInvoke.ps1 new file mode 100644 index 0000000..da71eaa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/New-TestNestedInvoke.ps1 @@ -0,0 +1,152 @@ +<# +.SYNOPSIS + Processes automated server build tasks for Windows machines in ServiceNow, triggered via PowerShell Universal. +.DESCRIPTION + This script connects to the ServiceNow API, retrieves open catalog tasks that match a specific filter for automated server build tasks, + and processes them. This script is designed to run as a scheduled task. It can optionally filter tasks by a specific SCTask number. +.PARAMETER SCTaskNum + The ServiceNow task number to filter the tasks. If not provided, all tasks matching the filter will be processed. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 + This example runs the script and processes all open tasks that match the filter for automated server build tasks. +.EXAMPLE + .\New-ITDWindowsVmBuildTask_Auto.ps1 -SCTaskNum 'SCTASK0012345' + This example runs the script and processes only the task with the specified SCTask number. +.NOTES + Ensure that the ServiceNow instance URL and credentials are correctly configured in the New-ITDServiceNowSession function. + This script is not supported in Linux. +#> +<# +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number | Select-Object -First 3 +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + { $_ -match "human review" } { + Write-Verbose -Message "Human review required, skipping" -Verbose + Break + } + { $_ -match "build step 2 complete" } { + # execute Step 3 + Write-Verbose -Message "Step 2 already complete, starting step 3" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + #$WorkNotesMsg = ("VMware build Step 3 started.`nPSU Job Id #" + $PSUJob.Id) + Break + } + { $_ -match "build Step 2 started"} { + Write-Verbose -Message "Step 2 already started, skipping" -Verbose + Break + } + { $_ -match "build step 1 complete" } { + # execute Step 2 + Write-Verbose -Message "Step 1 already complete, starting Step 2" -Verbose + # Determine if VMware or Azure and run appropriate build Step 2 function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 2" -Verbose + #Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step2.ps1" -SCTaskNum $SCTaskNum + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 2" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 2 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + { $_ -match "build Step 1 started"} { + Write-Verbose -Message "Step 1 already started, skipping" -Verbose + Break + } + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + If($null -eq $WorkNotesMsg){ + # do nothing + } Else { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{work_notes = $WorkNotesMsg } + } +} + +#> + +#Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot02.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot03.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot04.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot05.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot06.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot07.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot08.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot09.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot10.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot11.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot12.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot13.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot14.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" +Invoke-PSUScript -Name New-ITDWindowsVmAzure_Step1.ps1 -FQDN itdcopilot15.testnd.gov -DiskOsGB 128 -Subnet 10.21.29.96/27 -OS "Windows 11 24H2" -VMEnvironment 'Test' -AppName ITD-POC-Copilot -LicensingRestrictions "No Licensing Restrictions" -DiskDataGB 0 -VMSizeOverride "Standard_D4ds_v5" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-FormSubmission.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-FormSubmission.ps1 new file mode 100644 index 0000000..c974312 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-FormSubmission.ps1 @@ -0,0 +1,10 @@ +param( + [String] + $VMName +) + +$string = (Get-Date -UFormat "%Y%m%d%H%M%S") + " Hello World! $VMName" +Write-Output $string + + +Write-Output $User \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ITDSchedule.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ITDSchedule.ps1 new file mode 100644 index 0000000..c8db344 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ITDSchedule.ps1 @@ -0,0 +1,77 @@ +Param( + [string] + $SCTaskNum +) + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" -Verbose + $OpenTasks = $OpenTasks | Where-Object { $_.number.value -EQ $SCTaskNum } +} + +$AllRitms = [System.Collections.ArrayList]@() + +Write-Verbose -Message ("OpenTasks found: " + @($OpenTasks).Count) -Verbose + +ForEach ($OpenTask in $OpenTasks) { + $PSUJob = $null + $SCTask = $null + $shortdescription = $null + $shortdescription_hostname = $null + $WorkNotesMsg = $null + + $SCTaskNum = $OpenTask.number.Value + Write-Verbose -Message "Start $SCTaskNum" -Verbose + + try { + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $shortdescription = $SCTask.short_description.display_value + $shortdescription_hostname = $shortdescription.split(' ')[7] + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + <# + If ($AllRitms | Where-Object { $_.number.display_value -EQ $SCTask.request_item.display_value }) { + Write-Verbose -Message ("Ritm already in memory") -Verbose + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + Write-Verbose -Message "Ritm is not in memory, retrieve it" -Verbose + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } +#> + # check for step messages in SCTask work_notes and determine next step + switch ($SCTask.work_notes.display_value) { + Default { + # execute Step 1 + Write-Verbose -Message "No step messages found, starting Step 1" -Verbose + # Determine if VMware or Azure and run appropriate build function + switch ( ($Ritm.VariableSet | Where-Object host_name -EQ $shortdescription_hostname).target_platform ) { + 'azure' { + $target_platform = "Azure" + Write-Verbose "Invoking PSUScript for Azure Step 1" -Verbose + #$PSUJob = Invoke-PSUScript -Script "New-ITDWindowsVmAzure_Step1.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("Azure build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + 'vmware' { + $target_platform = "VMware" + Write-Verbose "Invoking PSUScript for VMware Step 1" -Verbose + $PSUJob = Invoke-PSUScript -Script "Get-HelloWorld.ps1" -SCTaskNum $SCTaskNum + $WorkNotesMsg = ("VMware build Step 1 started.`nPSU Job Id #" + $PSUJob.Id) + } + } + Break + } + } + + + } + catch { + Write-Error -Message $error[0] + } + + Write-Verbose -Message "End $SCTaskNum" -Verbose +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-InvokeZM.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-InvokeZM.ps1 new file mode 100644 index 0000000..4a5e672 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-InvokeZM.ps1 @@ -0,0 +1,5 @@ +$x=Invoke-PSUScript -Name Get-HelloWorld.ps1 -WorldName "zm" +Write-Warning $x.Id + +$x=Invoke-PSUScript -Name Get-HelloWorld.ps1 -WorldName "zo" +Write-Warning $x.Id diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-PSUVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-PSUVariable.ps1 new file mode 100644 index 0000000..808484f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-PSUVariable.ps1 @@ -0,0 +1,2 @@ +# It all starts with a single line of powershell code. +Write-Verbose -Message $Secret:ndgov_svcitdpsuwin.username -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ServiceNowConnectivity.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ServiceNowConnectivity.ps1 new file mode 100644 index 0000000..cd4df8b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ServiceNowConnectivity.ps1 @@ -0,0 +1,12 @@ +New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred -Verbose +$OpenTasks = Get-ServiceNowRecord -Table 'Incident' + +Write-Host $OpenTasks + + +New-ServiceNowSession -Url 'northdakotatest.service-now.com' -Credential $Secret:SNowVMCred -Verbose +$OpenTasks = Get-ServiceNowRecord -Table 'Incident' + +Write-Host $OpenTasks + + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ZM2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ZM2.ps1 new file mode 100644 index 0000000..a9fb0a9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/Test-ZM2.ps1 @@ -0,0 +1,2 @@ +### +Write-Warning -Message "Hello World!" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/test-sql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/test-sql.ps1 new file mode 100644 index 0000000..0b29182 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/ZM-Test/test-sql.ps1 @@ -0,0 +1,18 @@ + + switch ($env:computername) { + "ITDWINAUTOT1" { + New-UDTypography -Text 'NPD' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } + "ITDWINAUTOP1" { + New-UDTypography -Text 'PRD' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } + } + + $SqlQuery = "SELECT [PSUJobId],[DateTime],[ComputerName],[Status],[FullName] FROM [$Database].[dbo].[$Table]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/Dashboard.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/Dashboard.ps1 new file mode 100644 index 0000000..690ff2c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/Dashboard.ps1 @@ -0,0 +1,3 @@ +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/pages/home.ps1 new file mode 100644 index 0000000..c771a68 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Dashboard/pages/home.ps1 @@ -0,0 +1,13 @@ +New-UDPage -Url "/Home" -Name "Home" -Content { +New-UDTypography -text 'Home' -id 'homeText' +New-UDTextbox -id 'VMName' +} -Generated -Layout ( +New-UDPageLayout -Large @( +) -Medium @( + New-UDItemLayout -Id 'homeText' -Row 0 -Column 0 -RowSpan 1 -ColumnSpan 1 + New-UDItemLayout -Id 'VMName' -Row 0 -Column 1 -RowSpan 1 -ColumnSpan 1 +) -Small @( +) -ExtraSmall @( +) -ExtraExtraSmall @( + ) +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/DashboardTest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/DashboardTest.ps1 new file mode 100644 index 0000000..082d85a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/DashboardTest.ps1 @@ -0,0 +1,23 @@ +New-UDApp -Title 'DashboardTest' -Pages @( + New-UDPage -Name "test2" -Content { + New-UDForm -Content { + New-UDTextbox -Label 'VMName' -Id 'VMName' + New-UDTextbox -Label 'HoursToKeep' -Id 'HoursToKeep' + New-UDDatePicker -Label 'StartDate' -Id "StartDate" + New-UDTimePicker -Label 'StartTime' -Id "StartTime" + + } -OnSubmit { + #Show-UDToast -Message $EventData.txtTextField + #Show-UDToast -Message $EventData.chkCheckbox + #Invoke-PSUScript -Script 'Test-FormSubmission.ps1' -VMName $EventData.VMName + #"Current User = $User, StartDate = " + $EventData.StartDate + " " + $EventData.StartTime + + + + $StartDateTime = $EventData.StartDate.Date + $StartDateTime = $StartDateTime.AddHours($EventData.StartTime.Hour) + $StartDateTime = $StartDateTime.AddMinutes($EventData.StartTime.Minute) + Show-UDToast -Message ("Start Date/Time is: " + $StartDateTime) -Duration 20000 + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/test.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/test.ps1 new file mode 100644 index 0000000..1e07822 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/DashboardTest/pages/test.ps1 @@ -0,0 +1,10 @@ +New-UDPage -Url "/test" -Name "test" -Content { + +} -Generated -Layout ( +New-UDPageLayout -Large @( +) -Medium @( +) -Small @( +) -ExtraSmall @( +) -ExtraExtraSmall @( + ) +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 new file mode 100644 index 0000000..88924ce --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/ITD-WindowsServer_FileManagement.ps1 @@ -0,0 +1,25 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + switch($env:computername){ + "ITDWINAUTOT1" { + New-UDListItem -Label 'Remove-ITDExpiredFiles Log' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + } + "ITDWINAUTOP1" { + New-UDListItem -Label 'Remove-ITDExpiredFiles Log' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } + } + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + switch($env:computername){ + "ITDWINAUTOT1" { Get-UDPage -Name 'NPD' } + "ITDWINAUTOP1" { Get-UDPage -Name 'PRD' } + } +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 new file mode 100644 index 0000000..d37f42e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/PRD.ps1 @@ -0,0 +1,30 @@ +New-UDPage -Url "/PRD" -Name "PRD" -Content { +New-UDTypography -Text 'Remove Expired Files Log' + +switch($env:COMPUTERNAME){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = "Infra_WindowsServer_FileManagement_RemoveITDExpiredFiles_PRD" + } +} + + $SqlQuery = "SELECT [PSUJobId],[DateTime],[ComputerName],[Status],[FullName] FROM [$Database].[dbo].[$Table]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'PSUJobId' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' -ShowFilter + New-UDTableColumn -Property 'ComputerName' -Title 'ComputerName' -ShowFilter + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'FullName' -Title 'FullName' -ShowFilter + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Title "PRD" -Icon @{ + id = 'd0f3391d-efa6-4210-b4dd-ef0cad028382' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ITD-WindowsServer_FileManagement/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/Infra-ActiveDirectory_Object.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/Infra-ActiveDirectory_Object.ps1 new file mode 100644 index 0000000..ef91245 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/Infra-ActiveDirectory_Object.ps1 @@ -0,0 +1,17 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'Infra-ActiveDirectory.Object_NPD' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + New-UDListItem -Label 'Infra-ActiveDirectory.Object__PRD' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'NPD' + Get-UDPage -Name 'PRD' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/Infra-ActiveDirectory.Object_NPD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/Infra-ActiveDirectory.Object_NPD.ps1 new file mode 100644 index 0000000..72bc7e1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/Infra-ActiveDirectory.Object_NPD.ps1 @@ -0,0 +1,4 @@ +New-UDPage -Url "/NPD" -Name "Infra-ActiveDirectory.Object_NPD" -Content { +New-UDTypography -Text 'NPD' +} -Icon @{ + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/groups.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/groups.ps1 new file mode 100644 index 0000000..224a210 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/groups.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Groups' -Content { + New-UDTypography -Text 'Groups' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/users.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/users.ps1 new file mode 100644 index 0000000..1be780a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-ActiveDirectory_Object/pages/users.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Users' -Content { + New-UDTypography -Text 'Users' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/Infra-VMware.Snapshot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/Infra-VMware.Snapshot.ps1 new file mode 100644 index 0000000..6a620fd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/Infra-VMware.Snapshot.ps1 @@ -0,0 +1,30 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + switch($env:computername){ + "ITDWINAUTOT1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_NPD' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + } + "ITDWINAUTOP1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_PRD' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } + } +} + + New-UDListItem -Label 'Live Snapshots' -OnClick { + Invoke-UDRedirect -Url '/LiveSnapshots' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + switch($env:computername){ + "ITDWINAUTOT1" { Get-UDPage -Name 'NPD' } + "ITDWINAUTOP1" { Get-UDPage -Name 'PRD' } + } + Get-UDPage -Name 'LiveSnapshots' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/LiveSnapshots.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/LiveSnapshots.ps1 new file mode 100644 index 0000000..6ced34a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/LiveSnapshots.ps1 @@ -0,0 +1,26 @@ +New-UDPage -Url "/LiveSnapshots" -Name "LiveSnapshots" -Content { +New-UDForm -Content { + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + + } + } +} -OnSubmit { + Connect-ITDvCenter -Credential $Secret:svcitdvmsnapmgr + Show-UDToast -Message ("attempting query") - + $AllSnapshots = Get-Datacenter | Where-Object Name -notlike "Normandy*" | Get-VM | Get-Snapshot | Select-Object VM,Name,SizeGB,Created,Description + Disconnect-ITDvCenter + + New-UDTable -Columns @( + New-UDTableColumn -Property "VM" -Title "VM" -ShowFilter + New-UDTableColumn -Property 'Name' -Title 'Name' -ShowFilter + New-UDTableColumn -Property "SizeGB" -Title "SizeGB" + New-UDTableColumn -Property "Created" -Title "Created" + New-UDTableColumn -Property "Description" -Title "Description" + + ) -Data ($AllSnapshots) -ShowPagination -PageSize 20 -Dense +} +} -Title "LiveSnapshots" -Icon @{ + type = 'icon' + id = '74a7d396-2f35-4e10-a5c1-918f59bea61d' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/NPD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/NPD.ps1 new file mode 100644 index 0000000..e4fa6ab --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/NPD.ps1 @@ -0,0 +1,46 @@ +New-UDPage -Url "/NPD" -Name "NPD" -Content { +New-UDTypography -Text 'NPD' + New-UDForm -Content { + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextBox -Label "VMName" -Id VMName + New-UDTextBox -Label "DateTime" -Id DateTime + New-UDTextBox -Label "DurationHours" -Id DurationHours + New-UDTextBox -Label "Email" -Id Email + } + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDVMwareSnapshotTask.ps1' + VMName = $EventData.VMName; + DateTime = $EventData.DateTime; + DurationHours = $EventData.DurationHours; + Email = $EventData.Email + } + $InvokePSUScriuptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("attempting snapshot") + } + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[PSUJobIdRequest],[PSUJobIdDelete],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[Infra_VMware_VirtualMachine_VMSnapshots_NPD]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'Id' -Title 'Id' -ShowFilter + New-UDTableColumn -Property 'VMName' -Title 'VMName' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' + New-UDTableColumn -Property 'RequestedBy' -Title 'RequestedBy' -ShowFilter + New-UDTableColumn -Property 'DurationHours' -Title 'DurationHours' + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'NotifyEmail' -Title 'NotifyEmail' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdRequest' -Title 'PSUJobIDRequest' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdDelete' -Title 'PSUJobIDDelete' -ShowFilter + New-UDTableColumn -Property 'TakenDateTime' -Title 'TakenDateTime' + New-UDTableColumn -Property 'ExpireDateTime' -Title 'ExpireDateTime' + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Icon @{ + type = 'icon' + id = '3e16c7ba-54bd-4edb-b4f3-0e644f6bd656' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/PRD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/PRD.ps1 new file mode 100644 index 0000000..3452d21 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/PRD.ps1 @@ -0,0 +1,4 @@ +New-UDPage -Url "/PRD" -Name "PRD" -Content { +New-UDTypography -Text 'PRD' +} -Icon @{ + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/home.ps1 new file mode 100644 index 0000000..f8ef4cd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware.Snapshot/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 new file mode 100644 index 0000000..f2d6d03 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/Infra-VMware_Snapshot.ps1 @@ -0,0 +1,30 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + switch($env:computername){ + "ITDWINAUTOT1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_NPD' -OnClick { + Invoke-UDRedirect -Url '/NPD' + } + } + "ITDWINAUTOP1" { + New-UDListItem -Label 'Infra-VMware.Snapshot_PRD' -OnClick { + Invoke-UDRedirect -Url '/PRD' + } + } + } + + New-UDListItem -Label 'Live Snapshots' -OnClick { + Invoke-UDRedirect -Url '/LiveSnapshots' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + switch($env:computername){ + "ITDWINAUTOT1" { Get-UDPage -Name 'NPD' } + "ITDWINAUTOP1" { Get-UDPage -Name 'PRD' } + } + Get-UDPage -Name 'LiveSnapshots' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 new file mode 100644 index 0000000..e1303ac --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/PRD.ps1 @@ -0,0 +1,57 @@ +New-UDPage -Url "/PRD" -Name "PRD" -Content { +New-UDTypography -Text 'PRD' + <#New-UDForm -Content { + + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextBox -Label "VMName" -Id VMName + New-UDTextBox -Label "DateTime" -Id DateTime + New-UDTextBox -Label "DurationHours" -Id DurationHours + New-UDTextBox -Label "Email" -Id Email + } + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDVMwareSnapshotTask.ps1' + VMName = $EventData.VMName; + DateTime = $EventData.DateTime; + DurationHours = $EventData.DurationHours; + Email = $EventData.Email + } + $InvokePSUScriuptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("attempting snapshot") + } #> + +switch($env:COMPUTERNAME){ + "ITDWINAUTOT1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_NPD" + } + "ITDWINAUTOP1" { + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SnapshotTable = "Infra_VMware_VirtualMachine_VMSnapshots_PRD" + } +} + + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[PSUJobIdRequest],[PSUJobIdDelete],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [$Database].[dbo].[$SnapshotTable]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'Id' -Title 'Id' -ShowFilter + New-UDTableColumn -Property 'VMName' -Title 'VMName' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' + New-UDTableColumn -Property 'RequestedBy' -Title 'RequestedBy' -ShowFilter + New-UDTableColumn -Property 'DurationHours' -Title 'DurationHours' + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'NotifyEmail' -Title 'NotifyEmail' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdRequest' -Title 'PSUJobIDRequest' -ShowFilter + New-UDTableColumn -Property 'PSUJobIdDelete' -Title 'PSUJobIDDelete' -ShowFilter + New-UDTableColumn -Property 'TakenDateTime' -Title 'TakenDateTime' + New-UDTableColumn -Property 'ExpireDateTime' -Title 'ExpireDateTime' + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Title "PRD" -Icon @{ + id = 'd0f3391d-efa6-4210-b4dd-ef0cad028382' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_Snapshot/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/Infra-VMware_SnapshotReview.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/Infra-VMware_SnapshotReview.ps1 new file mode 100644 index 0000000..58b2144 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/Infra-VMware_SnapshotReview.ps1 @@ -0,0 +1,43 @@ +New-UDApp -Title 'Infra-VMware_Snapshot_NPD' -Content { + New-UDForm -Content { + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextBox -Label "VMName" -Id VMName + New-UDTextBox -Label "DateTime" -Id DateTime + New-UDTextBox -Label "DurationHours" -Id DurationHours + New-UDTextBox -Label "Email" -Id Email + } + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDVMwareSnapshotRequest.ps1' + VMName = $EventData.VMName; + DateTime = $EventData.DateTime; + DurationHours = $EventData.DurationHours; + Email = $EventData.Email + } + $InvokePSUScriuptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("attempting snapshot") + } + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SqlQuery = "SELECT [ID],[VMName],[DateTime],[RequestedBy],[DurationHours],[Status],[NotifyEmail],[PSUJobIdRequest],[PSUJobIdSchedule],[PSUJobIdDelete],[TakenDateTime],[ExpireDateTime],[DeleteDateTime] FROM [ITD-Systems-Automation].[dbo].[Infra_VMware_VirtualMachine_VMSnapshots_NPD]" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'Id' -Title 'Id' -ShowFilter + New-UDTableColumn -Property 'VMName' -Title 'VMName' + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' + New-UDTableColumn -Property 'RequestedBy' -Title 'RequestedBy' + New-UDTableColumn -Property 'DurationHours' -Title 'DurationHours' + New-UDTableColumn -Property 'Status' -Title 'Status' + New-UDTableColumn -Property 'NotifyEmail' -Title 'NotifyEmail' + New-UDTableColumn -Property 'PSUJobIdRequest' -Title 'PSUJobIDRequest' + New-UDTableColumn -Property 'PSUJobIdSchedule' -Title 'PSUJobIDSchedule' + New-UDTableColumn -Property 'PSUJobIdDelete' -Title 'PSUJobIDDelete' + New-UDTableColumn -Property 'TakenDateTime' -Title 'TakenDateTime' + New-UDTableColumn -Property 'ExpireDateTime' -Title 'ExpireDateTime' + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/pages/SnapshotReview.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/pages/SnapshotReview.ps1 new file mode 100644 index 0000000..0d8c2f9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/Infra-VMware_SnapshotReview/pages/SnapshotReview.ps1 @@ -0,0 +1,4 @@ +New-UDPage -Name "SnapshotReview" -Content { + +} -Title "SnapshotReview" -Icon @{ + } -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 new file mode 100644 index 0000000..cc997dc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/NewITDADServiceAccount.ps1 @@ -0,0 +1,13 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'AD Service Accounts' -OnClick { + Invoke-UDRedirect -Url '/ADServiceAccount' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'ADServiceAccount' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 new file mode 100644 index 0000000..ccb8238 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/ADServiceAccount.ps1 @@ -0,0 +1,34 @@ +New-UDPage -Url "/ADServiceAccount" -Name "ADServiceAccount" -Content { +New-UDTypography -Text 'ADServiceAccount' + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $SqlQuery = "SELECT TOP (1000) [RequestedBy] + ,[PSUJobId] + ,[SamAccountName] + ,[Description] + ,[PasswordstateTitle] + ,[PasswordstateList] + ,[SnowCHGNum] + ,[Status] + ,[DomainName] + ,[DateTime] + FROM [ITD-Systems-Automation].[dbo].[Infra_ActiveDirectory_Object_NewITDADServiceAccount_PRD] + ORDER BY [DateTime] DESC" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'PSUJobId' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'DateTime' -Title 'DateTime' -ShowFilter + New-UDTableColumn -Property 'RequestedBy' -Title 'PSUJobId' -ShowFilter + New-UDTableColumn -Property 'SamAccountName' -Title 'SamAccountName' -ShowFilter + New-UDTableColumn -Property 'PasswordstateList' -Title 'PasswordstateList' -ShowFilter + New-UDTableColumn -Property 'PasswordstateTitle' -Title 'PasswordstateTitle' -ShowFilter + New-UDTableColumn -Property 'SnowCHGNum' -Title 'SnowCHGNum' -ShowFilter + New-UDTableColumn -Property 'Status' -Title 'Status' -ShowFilter + New-UDTableColumn -Property 'Domainname' -Title 'DomainName' -ShowFilter + + ) -Data ($SqlRecords | Sort-Object -Descending Id) -ShowPagination -PageSize 20 -Dense +} -Icon @{ + type = 'icon' + id = '259b4c05-17df-4440-9907-57ab4df1e6c9' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccount/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/NewITDADServiceAccountRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/NewITDADServiceAccountRequest.ps1 new file mode 100644 index 0000000..c87d11a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/NewITDADServiceAccountRequest.ps1 @@ -0,0 +1,49 @@ +New-UDApp -Title 'SyncVMwareVMtoSharePoint' -Pages @( + New-UDPage -Name "Home" -Content { + New-UDForm -Content { + New-UDTypography -Text 'Enter the information below (all fields required) and click the Submit button' + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Label 'RequestedForEmail' -Id RequestedForEmail + New-UDTextbox -Label 'ADDomain' -Id ADDomain + New-UDTextbox -Label 'SamAccountName' -Id SamAccountName + New-UDTextbox -Label 'Description' -Id Description + New-UDTextbox -Label 'PasswordstateList' -Id PasswordstateList + New-UDTextbox -Label 'PasswordstateTitle' -Id PasswordstateTitle + } + } + } -OnValidate { + $FormContent = $EventData + + if ($EventData.RequestedForEmail -eq $null -or $EventData.RequestedForEmail -eq '' -or $EventData.ADDomain -eq $null -or $EventData.ADDomain -eq '' -or $EventData.SamAccountName -eq $null -or $EventData.SamAccountName -eq '' -or $EventData.Description -eq $null -or $EventData.Description -eq '' -or $EventData.PasswordstateList -eq $null -or $EventData.PasswordstateList -eq '' -or $EventData.PasswordstateTitle -eq $null -or $EventData.PasswordstateTitle -eq '') { + # ('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI') + New-UDFormValidationResult -ValidationError "All fields are required." + } + else { + if ($FormContent.ADDomain -ne 'nd.gov') { + New-UDFormValidationResult -ValidationError "Only nd.gov ADDomain is supported at this time." + } + else { + If (@('Office365', 'VMware_Systems', 'CSRC', 'Shared Linux Password List', 'Peoplesoft Share PW', 'Cohesity', 'VDI') -notcontains $EventData.PasswordstateList) { + New-UDFormValidationResult -ValidationError "PasswordstateList must match one of the following: VMware_Systems, Cohesity, VDI, Office365, CSRC, Shared Linux Password List, Peoplesoft Share PW" + } + } + New-UDFormValidationResult -Valid + } + } -OnSubmit { + $InvokePSUScriptParams = @{ + Script = 'New-ITDADServiceAccountRitm_script.ps1'; + RequestedForEmail = $EventData.RequestedForEmail + ADDomain = $EventData.ADDomain + SamAccountName = $EventData.SamAccountName + Description = $EventData.Description + PasswordstateList = $EventData.PasswordstateList + PasswordstateTitle = $EventData.PasswordstateTitle + + } + $InvokePSUScriptResult = Invoke-PSUScript @InvokePSUScriptParams -Wait + Show-UDToast -Message ("ServiceNow Request " + $InvokePSUScriptResult.number + " created on behalf of $User" ) -Duration 100000 + + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDADServiceAccountRequest/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/NewITDVMwareVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/NewITDVMwareVMSnapshotTask.ps1 new file mode 100644 index 0000000..9525942 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/NewITDVMwareVMSnapshotTask.ps1 @@ -0,0 +1,16 @@ +New-UDApp -Title 'NewITDVMwareVMSnapshotTask' -Pages @( + New-UDPage -Name "NewITDVMwareVMSnapshotTask" -Content { + New-UDForm -Content { + New-UDTextbox -Label 'VMName' -Id 'VMName' + New-UDTextbox -Label 'HoursToKeep' -Id 'HoursToKeep' -Maximum 72 -Minimum 1 -Type number + New-UDDatePicker -Label 'StartDate' -Id "StartDate" + New-UDTimePicker -Label 'StartTime' -Id "StartTime" + + } -OnSubmit { + $StartDateTime = $EventData.StartDate.Date + $StartDateTime = $StartDateTime.AddHours($EventData.StartTime.Hour) + $StartDateTime = $StartDateTime.AddMinutes($EventData.StartTime.Minute) + Show-UDToast -Message ("Start Date/Time is: " + $StartDateTime + "`n User is " + $User) -Duration 20000 + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/NewITDVMwareVMSnapshotTask/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/PSUVariableReview.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/PSUVariableReview.ps1 new file mode 100644 index 0000000..3c1ab69 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/PSUVariableReview.ps1 @@ -0,0 +1,17 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -Icon (New-UDIcon -Icon Home) -OnClick { + Invoke-UDRedirect -Url '/home' + } + New-UDListItem -Label 'Users' -Icon (New-UDIcon -Icon User) -OnClick { + Invoke-UDRedirect -Url '/users' + } + New-UDListItem -Label 'Groups' -Icon (New-UDIcon -Icon Users) -OnClick { + Invoke-UDRedirect -Url '/groups' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' + Get-UDPage -Name 'users' + Get-UDPage -Name 'groups' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/users.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/users.ps1 new file mode 100644 index 0000000..8bd127c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariableReview/pages/users.ps1 @@ -0,0 +1,26 @@ +New-UDPage -Url "/Users" -Name "Users" -Content { +New-UDTypography -Text 'Roles assigned to this user:' +New-UDList -Content { + $Roles | ForEach-Object{ + New-UDListItem -Label $_ + } +} + + +New-UDTypography -Text 'Variables this user can access:' +$AllPSUVariables = Get-PSUVariable +$TableData = $AllPSUVariables | Select *,@{n='RoleStr';e={$_.Role -join ", "}},@{n='SecretValue';e={$SecretValue=Get-Childitem ("Secret:" + $_.Name) -ErrorAction SilentlyContinue;If($SecretValue -is [string]){"secure_string"}Else{$SecretValue}}},@{n='SecretUsername';e={(Get-Childitem ("Secret:" + $_.Name) -ErrorAction SilentlyContinue).Username}} + +New-UDTable -Columns @( + New-UDTableColumn -Property 'Name' -Title 'Name' -ShowFilter + New-UDTableColumn -Property 'RoleStr' -Title 'Role' -ShowFilter + New-UDTableColumn -Property 'Type' -Title 'Type' -ShowFilter + New-UDTableColumn -Property 'Value' -Title 'Value' -ShowFilter + New-UDTableColumn -Property 'Secret' -Title 'Secret' -ShowFilter + New-UDTableColumn -Property 'SecretValue' -Title 'SecretValue' -ShowFilter + New-UDTableColumn -Property 'SecretUsername' -Title 'SecretUsername' -ShowFilter + ) -Data $TableData -Dense +} -Title "Users" -Icon @{ + type = 'icon' + id = '37c13667-6c5a-4cb1-a16b-49eaddd96d03' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/PSUVariables.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/PSUVariables.ps1 new file mode 100644 index 0000000..c0144d0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/PSUVariables.ps1 @@ -0,0 +1,3 @@ +New-UDApp -Title 'PSUVariable' -Content { + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/PSUVariables/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 new file mode 100644 index 0000000..690ff2c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/RemoveITDExpiredFiles.ps1 @@ -0,0 +1,3 @@ +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/RemoveITDExpiredFiles/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/ServiceNow.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/ServiceNow.ps1 new file mode 100644 index 0000000..30142c6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/ServiceNow.ps1 @@ -0,0 +1,33 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'CMDB Ci Lookup' -OnClick { + Invoke-UDRedirect -Url '/CMDBServerList' + } + New-UDListItem -Label 'Server Build Request V1 (Current) Lookup' -OnClick { + Invoke-UDRedirect -Url '/ServerBuildRequestV1' + } + New-UDListItem -Label 'Application Server V2 (Previous) Lookup' -OnClick { + Invoke-UDRedirect -Url '/ApplicationServerV2' + } + New-UDListItem -Label 'AppNameLookup' -OnClick { + Invoke-UDRedirect -Url '/AppNameLookup' + } + New-UDListItem -Label 'CiLookup' -OnClick { + Invoke-UDRedirect -Url '/CiLookup' + } + New-UDListItem -Label 'AzureSizeHelper' -OnClick { + Invoke-UDRedirect -Url '/AzureVmSizeHelper' + } +) +AppNameLookup.ps1 - /AppNameLookup +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'CMDBServerList' + Get-UDPage -Name 'ServerBuildRequestV1' + Get-UDPage -Name 'ApplicationServerV2' + Get-UDPage -Name 'AppNameLookup' + Get-UDPage -Name 'CiLookup' + Get-UDPage -Name 'AzureVmSizeHelper' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AppNameLookup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AppNameLookup.ps1 new file mode 100644 index 0000000..0834d7d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AppNameLookup.ps1 @@ -0,0 +1,58 @@ +New-UDPage -Url "/AppNameLookup" -Name "AppNameLookup" -Content { +New-UDTypography -Id "disclaimer" -Text "This is querying the cmdb_ci_service_auto table in ServiceNow. This is live data being shown." + + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $PropertyList = @( + @{ + name = "name"; + expression = { $_.name.display_value }; + }, + @{ + name = "sys_id"; + expression = { $_.sys_id.value } ; + }, + @{ + name = "u_primary_systems_admin"; + expression = { $_.u_primary_systems_admin.display_value } ; + }, + @{ + name = "u_secondary_systems_admin"; + expression = { $_.u_secondary_systems_admin.display_value } ; + }, + @{ + name = 'u_systems_owner'; + expression = { $_.u_systems_owner.display_value}; + } + ) + #$Result = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("nameLIKE" + $EventData.CiName) -IncludeTotalCount | Select-Object -Property $PropertyList + $GetITDServiceNowRecordParams = @{ + Table = 'cmdb_ci_service_auto'; + IncludeTotalCount = $true; + Fields = @( + 'name', + 'sys_id', + 'u_primary_systems_admin', + 'u_secondary_systems_admin', + 'u_systems_owner' + ) + } + $Result = Get-ITDServiceNowRecord @GetITDServiceNowRecordParams | Select-Object -Property $PropertyList + $CmdbCiUrl = "https://northdakota.service-now.com/nav_to.do?uri=" + $Result.sys_class_name + ".do?sys_id=" + $Result.sys_id + + New-UDTable -Columns @( + New-UDTableColumn -Property 'SNowUrl' -Title 'CmdbCiUrl' -Render { #https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_win_server.do?sys_id=8bc3ecd11b0154509d7ada01dd4bcb59 + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_service_auto.do?sys_id=" + $EventData.sys_id) -Id "lnkSNow" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + New-UDTableColumn -Property 'name' -Title 'name' -ShowSort -ShowFilter + #New-UDTableColumn -Property 'sys_id' -Title 'sys_id' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_primary_systems_admin' -Title 'u_primary_systems_admin' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_secondary_systems_admin' -Title 'u_secondary_systems_admin' -ShowSort -ShowFilter + New-UDTableColumn -Property 'u_systems_owner' -Title 'u_systems_owner' -ShowSort -ShowFilter + ) -Data ($Result | sort-object Name) -ShowPagination -Dense -PageSize 50 +} -Title "AppNameLookup" -Icon @{ + id = '9fdceac8-807e-4d5e-acda-3d477d77fdb4' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 new file mode 100644 index 0000000..5ca0959 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ApplicationServerV2.ps1 @@ -0,0 +1,25 @@ +New-UDPage -Url "/ApplicationServerV2" -Name "ApplicationServerV2" -Content { +New-UDTypography -Text 'Application Server request items (RITMs) submitted between 2023/02/27 and 2024/06/25 in which the field "VM Work Needed" is set to "Yes"' + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = 'ServiceNow_RitmDump_ApplicationServerV2' + + $SqlQuery = "SELECT [number],[sys_id],[opened_at],[requested_for],[short_description],[request_type],[application_name],[environment],[additional_comments],[vm_work_needed],[server_name],[host_name],[server_type],[operating_system],[target_platform],[processors],[memory_gb],[cidr_block],[data_center],[licensing_restrictions],[agency_name],[application_info],[support_hours],[dr_protection],[startup_priority],[disk_1_os],[disk_2_swap_disk],[disk_3],[disk_4],[disk_5],[disk_6],[disk_7],[disk_8],[disk_9],[disk_10],[disk_11],[disk_12],[disk_13],[disk_14],[disk_15],[disk_16] FROM [$Database].[dbo].[$Table] WHERE vm_work_needed = '1'" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'number' -Title 'number' -ShowSort + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' + New-UDTableColumn -Property 'server_name' -Title 'server_name' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter + ) -Data ($SqlRecords | Select *,@{n='Open';e={$_.sys_id}} | Sort-Object -Descending number) -Dense -ShowPagination -PageSize 20 +} -Title "ApplicationServerV2" -Icon @{ + id = 'd9dc64f6-9f4b-432a-866a-d3189529528b' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 new file mode 100644 index 0000000..b0ea0b4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/AzureVmSizeHelper.ps1 @@ -0,0 +1,23 @@ +New-UDPage -Url "/AzureVmSizeHelper" -Name "AzureVmSizeHelper" -Content { +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = $Secret:azure_iaasserviceprincipal +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +$TableData = Get-AzVmSize -Location centralus | Select *,` + @{n='MemoryInGB';e={$_.MemoryInMb / 1024}}, ` + @{n='OSDiskSizeInGB'; e={$_.OsDiskSizeInMb / 1024}}, ` + @{n='ResourceDiskSizeInGB'; e={$_.ResourceDiskSizeInMB / 1024}} | Sort-Object NumberOfCores,MemoryInGB + +New-UDTable -Columns @( + New-UDTableColumn -Property 'Name' -Title 'Name' -ShowSort -ShowFilter + New-UDTableColumn -Property 'NumberOfCores' -Title 'NumberOfCores' -ShowSort -ShowFilter + New-UDTableColumn -Property 'MemoryInGB' -Title 'MemoryInGB' -ShowFilter -ShowSort + New-UDTableColumn -Property 'OSDiskSizeInGB' -Title 'OSDiskSizeInGB' -ShowFilter -ShowSort + New-UDTableColumn -Property 'ResourceDiskSizeInGB' -Title 'ResourceDiskSizeInGB' -ShowFilter -ShowSort +) -Data $TableData -Dense +} -Title "AzureVmSizeHelper" -Icon @{ + type = 'icon' + id = 'f45c0541-5f78-4c00-899b-548e1bbabb04' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CMDBServerList.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CMDBServerList.ps1 new file mode 100644 index 0000000..e7fd3bd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CMDBServerList.ps1 @@ -0,0 +1,154 @@ +New-UDPage -Url "/CMDBServerList" -Name "CMDBServerList" -Content { +# Use Get-UDPage -Name 'CmdbServer' to use this page in your dashboard + +<# + New-UDCard -Content { + New-UDList -children { + New-UDListItem -Label "Enter the Name of the Cmdb Ci. Usually host name, not FQDN. `nFor example: itdsccmp2.nd.gov, enter itdsccmp2. The search is using 'LIKE' comparsion operator, so wildcards are automatically applied at both sides of the entered value. " + New-UDListItem -Label 'This search is a live query of the ServiceNow Cmdb.' + New-UDListItem -Label 'This is a work in progress. Use at your own discretion.' + } + }#> + + + + +New-UDForm -Id 'CiLookup' -Content { + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Id 'CiName' + } + } +} -OnValidate { + $FormContent = $EventData + if ($FormContent.CiName -eq $null -or $FormContent.VMName -eq '') { + New-UDFormValidationResult -ValidationError "CiName is required" + } + else { + New-UDFormValidationResult -Valid + } +} -OnSubmit { + Show-UDToast -Message ("Querying ServiceNow table cmdb_ci_server for record with name " + $EventData.Name) -Duration 20000 + + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + $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_application_svc"; + expression = { $_.u_nd_application_svc.display_value } + }, + @{ + name = "u_nd_licensing_restrictions"; + expression = { $_.u_nd_licensing_restrictions.display_value } + }, + @{ + name = "u_support_hours"; + expression = { $_.u_support_hours.display_value } + }, + @{ + name = "u_nd_dr_protection"; + expression = { $_.u_nd_dr_protection.display_value }; + }, + @{ + name = "u_srm_recovery_type"; + expression = { $_.u_srm_recovery_type.display_value } + }, + @{ + name = "os"; + expression = { $_.os.display_value } + }, + @{ + name = "os_version"; + expression = { $_.os_version.display_value } + }, + @{ + name = "model_id"; + expression = { $_.model_id.display_value } + } + ) + #$Result = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("nameLIKE" + $EventData.CiName) -IncludeTotalCount | Select-Object -Property $PropertyList + $GetITDServiceNowRecordParams = @{ + #Filter = "model_id=3161ee6c1bf810502653997fbd4bcb4c^ORmodel_id%253Da75f244c1bd75014bba0113fad4bcb72" + Filter = "model_idLIKEVMware^ORmodel_idLIKEMicrosoft" + Table = 'cmdb_ci_server'; + IncludeTotalCount = $true; + Fields = @( + 'name', + 'sys_id', + 'dns_domain', + 'sys_class_name', + 'operational_status', + 'environment', + 'u_nd_type', + 'model_id', + 'os', + 'os_version', + 'u_nd_application_svc', + 'u_nd_licensing_restrictions', + 'u_nd_dr_protection', + 'u_srm_recovery_type', + 'u_support_hours' + ) + } + $Result = Get-ITDServiceNowRecord @GetITDServiceNowRecordParams | Select-Object -Property $PropertyList + $CmdbCiUrl = "https://northdakota.service-now.com/nav_to.do?uri=" + $Result.sys_class_name + ".do?sys_id=" + $Result.sys_id + + New-UDTable -Columns @( + New-UDTableColumn -Property 'CmdbCiUrl' -Title 'CmdbCiUrl' -Render { #https://northdakota.service-now.com/nav_to.do?uri=cmdb_ci_win_server.do?sys_id=8bc3ecd11b0154509d7ada01dd4bcb59 + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=" + $EventData.sys_class_name + ".do?sys_id=" + $EventData.sys_id) -Id "lnkCmdbCi" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + New-UDTableColumn -Property 'name' -Title 'name' -ShowSort -ShowFilter + New-UDTableColumn -Property 'dns_domain' -Title 'dns_domain' -ShowFilter + New-UDTableColumn -Property 'u_nd_application_svc' -Title 'u_nd_application_svc' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableCOlumn -Property 'operational_status' -Title 'operational_status' -ShowFilter + New-UDTableColumn -Property 'u_nd_type' -Title 'u_nd_type' -ShowFilter + #New-UDTableColumn -Property 'model_id' -Title 'model_id' -ShowFilter + #New-UDTableColumn -Property 'os' -Title 'os' -ShowFilter + #New-UDTableColumn -Property 'os_version' -Title 'os_version' -ShowFilter + New-UDTableColumn -Property 'u_nd_licensing_restrictions' -Title 'u_nd_licensing_restrictions' -ShowFilter + New-UDTableColumn -Property 'u_support_hours' -Title 'u_support_hours' -ShowFilter + New-UDTableColumn -Property 'u_nd_dr_protection' -Title 'u_nd_dr_protection' -ShowFilter + New-UDTableColumn -Property 'u_srm_recovery_type' -Title 'u_srm_recovery_type' -ShowFilter + ) -Data ($Result | sort-object Name) -ShowPagination -Dense -PageSize 50 + + +} -OnProcessing { + +} + + +New-UDCard -Id 'Result' +} -Title "CMDBServerList" -Icon @{ + id = 'dc0de7d9-022b-4e24-a7c7-7f0e59710542' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiLookup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiLookup.ps1 new file mode 100644 index 0000000..832677d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiLookup.ps1 @@ -0,0 +1,97 @@ +New-UDPage -Url "/CiLookup" -Name "CiLookup" -Content { +New-UDGrid -Container -Children { + New-UDGrid -Item -ExtraSmallSize 4 -Children { + New-UDCard -Title "General Information" -Content { + #New-UDButton -Text "Button 1" + New-UDRow -Columns { + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "Name" -Id "Name" -Value "itddefghijklmno.ndcloud.gov" -FullWidth + } + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "LicensingRestrictions" -Id "LicensingRestrictions" -Value "Microsoft SQL Enterprise" + } + } + } + + } + New-UDGrid -Item -ExtraSmallSize 4 -Children { + New-UDCard -Title "Support Information" -Content { + #New-UDButton -Text "Button 2" + New-UDRow -Columns { + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "AppName" -Id "AppName" + } + New-UDColumn -Size 4 -Content { + New-UDTextBox -Label "Support Hours" -Id "Support Hours" + } + } + } + } + } -Id "GridGeneral" + +New-UDContainer -Content { + New-UDLayout -Columns 2 - -Content { + #New-UDTypography "Row 1, Col 1" + New-UDTextBox -Label "Name" -Value "itddefghijklmno.ndcloud.gov" -FullWidth + #New-UDTypography "Row 1, Col 2" + New-UDTextBox -Label "AppName" -Value "Infra-POS-SomeStupidApp" -FullWidth + New-UDTypography "Row 2, Col 1" + New-UDTypography "Row 2, Col 2" + } + } + +$tablePwd = [ordered]@{ + 'Password Expiration' = "itdsomething.nd.gov" + 'Account Expiration' = "ITD-POS-StupidName" + 'Last Logon Timestamp' = "Microsoft SQL Enterperise" +} + + +$Data = , @($tablePwd.GetEnumerator()) +$DateColumns = @( +New-UDTableColumn -Property Name -Title " " +New-UDTableColumn -Property Value -Title " " +) +New-UDTable -Id "PasswordInfo" -Title "Password and Account Info" -Data $Data[0] -Columns $DateColumns -Dense + + + + + + + +New-UDButton -Text 'Full Width' -OnClick { + Show-UDModal -Content { + New-UDGrid -Container -Children { + New-UDCard -Title "General" -Content { + New-UDElement -Tag 'div' -Id 'addElement' + New-UDTextBox -Id "Name" -Label "Name" -Value "servernamehere.nd.gov" + New-UDTextBox -Id "Operational Status" -Label "Status" -Value "Operational" + New-UDTextBox -Id "AppName" -Label "AppName" -Value "ITD-POS-StupidNameHere" + New-UDTextBox -Id "Support Hours" -Label "Support Hours" -Value "All Day Every Day" + } + New-UDCard -Title "Hardware" -Content { + New-UDTextBox -Id "Datacenter" -Label "Datacenter" -Value "Bismarck" + New-UDTextBox -Id "Environment" -Label "Environment" -Value "Production" + New-UDTextBox -Id "DR Protection" -Label "DR Protection" -Value "VMware: RPO 04:00" + New-UDTextBox -Id "Datacenter" -Label "Datacenter" -Value "Bismarck" + New-UDTextBox -Id "Environment" -Label "Environment" -Value "Production" + New-UDTextBox -Id "DR Protection" -Label "DR Protection" -Value "VMware: RPO 04:00" + New-UDTextBox -Id "OperatingSystem" -Label "Operating System" -Value "Windows Server 2022" + New-UDTextBox -Id "CPU" -Label "CPU" -Value "4" + New-UDTextBox -Id "MemoryGB" -Label "MemoryGB" -Value "12" + New-UDTextBox -Id "DiskGB" -Label "DiskGB" -Value "1197" + } + New-UDCard -Title "Software" -Content { + New-UDTextBox -Id "LicensingRestrictions" -Label "LicensingRestrictions" -Value "Microsoft SQL Enterprise" + New-UDTextBox -Id "OperatingSystem" -Label "Operating System" -Value "Windows Server 2022" + } + } + + #New-UDDynamic + } -FullWidth -MaxWidth 'md' +} +} -Title "CiLookup" -Icon @{ + id = '3743b2ed-0278-4678-8a47-e22ad4514afb' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiTest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiTest.ps1 new file mode 100644 index 0000000..6306b88 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/CiTest.ps1 @@ -0,0 +1,4 @@ +New-UDPage -Url "/CiTest" -Name "CiTest" -Content { + +} -Title "CiTest" -Icon @{ + } -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 new file mode 100644 index 0000000..2f12b45 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/ServerBuildRequestV1.ps1 @@ -0,0 +1,39 @@ +New-UDPage -Url "/ServerBuildRequestV1" -Name "ServerBuildRequestV1" -Content { +New-UDTypography -Text "`nServer Build Request request items (RITMs) submitted after 2024/06/25" + +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = 'ServiceNow_RitmDump_ServerBuildRequestV1' + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$SqlQuery = "SELECT [RitmNum], + [RitmSysId], + [opened_at], + [requested_for], + [request_type], + [environment] + ,[host_name_ref] + ,[host_name] + FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1]" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + + +New-UDTable -Dense -ShowPagination -PageSize 20 -Size small -Data ($SqlRecords | Sort-Object -Descending opened_at) -Columns @( + New-UDTableColumn -Property 'RitmUrl' -Title 'RitmUrl' -Render { + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=sc_req_item.do?sys_id=" + $EventData.RitmSysId) -Id "lnkRitm" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + + New-UDTableColumn -Property 'RitmNum' -Title 'RitmNum' -ShowFilter + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + #New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter +) +} -Title "ServerBuildRequestV1" -Icon @{ + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/home.ps1 new file mode 100644 index 0000000..b2d9d89 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNow/pages/home.ps1 @@ -0,0 +1,11 @@ +New-UDPage -Url "/Home" -Name "Home" -Content { +New-UDTypography -text 'Use left side navigation to view various ServiceNow queries' -id 'homeText' -noWrap +} -Generated -Layout ( +New-UDPageLayout -Large @( + New-UDItemLayout -Id 'homeText' -Row 0 -Column 0 -RowSpan 1 -ColumnSpan 1 +) -Medium @( +) -Small @( +) -ExtraSmall @( +) -ExtraExtraSmall @( + ) +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 new file mode 100644 index 0000000..d087b25 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/ServiceNowDumps.ps1 @@ -0,0 +1,21 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -OnClick { + Invoke-UDRedirect -Url '/Home' + } + New-UDListItem -Label 'ServerBuildRequestV1' -OnClick { + Invoke-UDRedirect -Url '/ServerBuildRequestV1' + } + New-UDListItem -Label 'ApplicationServerV2' -OnClick { + Invoke-UDRedirect -Url '/ApplicationServerV2' + } + New-UDListItem -Label 'SpCmdbCompare' -OnClick { + Invoke-UDRedirect -Url '/SpCmdbCompare' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'Home' + Get-UDPage -Name 'ApplicationServerV2' + Get-UDPage -Name 'ServerBuildRequestV1' + Get-UDPage -Name 'SpCmdbCompare' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 new file mode 100644 index 0000000..f01d71b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ApplicationServerV2.ps1 @@ -0,0 +1,25 @@ +New-UDPage -Url "/ApplicationServerV2" -Name "ApplicationServerV2" -Content { +New-UDTypography -Text 'Application Server request items (RITMs) submitted between 2023/02/27 and 2024/06/25 in which the field "VM Work Needed" is set to "Yes"' + + + $ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" + $Database = "ITD-Systems-Automation" + $Table = 'ServiceNow_RitmDump_ApplicationServerV2' + + $SqlQuery = "SELECT [number],[sys_id],[opened_at],[requested_for],[short_description],[request_type],[application_name],[environment],[additional_comments],[vm_work_needed],[server_name],[host_name],[server_type],[operating_system],[target_platform],[processors],[memory_gb],[cidr_block],[data_center],[licensing_restrictions],[agency_name],[application_info],[support_hours],[dr_protection],[startup_priority],[disk_1_os],[disk_2_swap_disk],[disk_3],[disk_4],[disk_5],[disk_6],[disk_7],[disk_8],[disk_9],[disk_10],[disk_11],[disk_12],[disk_13],[disk_14],[disk_15],[disk_16] FROM [$Database].[dbo].[$Table] WHERE vm_work_needed = '1'" + $SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + New-UDTable -Columns @( + New-UDTableColumn -Property 'number' -Title 'number' -ShowSort + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' + New-UDTableColumn -Property 'server_name' -Title 'server_name' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter + ) -Data ($SqlRecords | Select *,@{n='Open';e={$_.sys_id}} | Sort-Object -Descending number) -Dense -ShowPagination -PageSize 20 +} -Icon @{ + type = 'icon' + id = 'e91ed4ef-cecd-448a-9204-2b453db9db03' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/Home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/Home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/Home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 new file mode 100644 index 0000000..c4acfe2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/ServerBuildRequestV1.ps1 @@ -0,0 +1,130 @@ +New-UDPage -Url "/ServerBuildRequestV1" -Name "ServerBuildRequestV1" -Content { +New-UDForm -Content { + New-UDTypography -Text 'To sync vCenter to Sharepoint, enter a VMware VM name below and click the Submit button' + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Id 'VMName' + } + } +} -OnValidate { + $FormContent = $EventData + if ($FormContent.VMName -eq $null -or $FormContent.VMName -eq '') { + New-UDFormValidationResult -ValidationError "VMName is required" + } + else { + New-UDFormValidationResult -Valid + } +} -OnSubmit { + Show-UDToast -Message ($EventData.VMName + " sync in progress.") -Duration 5000 + + Invoke-PSUScript -Script 'Sync-ITDVMwareVMMetadataToSharePoint.ps1' -VMName $EventData.VMName -Wait | Out-Null + + Show-UDToast -Message ($EventData.VMName + " sync finished.") -Duration 10000 +} -OnProcessing { + New-UDTypography -Text ("Syncing " + $EventData.VMName + " ...") + New-UDProgress +} + +New-UDTypography -Text "`nServer Build Request request items (RITMs) submitted after 2024/06/25" + +$ServerInstance = "itdintsql22p1.nd.gov\INTSQL22P1" +$Database = "ITD-Systems-Automation" +$Table = 'ServiceNow_RitmDump_ServerBuildRequestV1' + +New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + +$SqlQuery = "SELECT [RitmNum], + [RitmSysId], + [opened_at], + [requested_for], + [request_type], + [environment] + ,[host_name_ref] + ,[host_name] + FROM [ITD-Systems-Automation].[dbo].[ServiceNow_RitmDump_ServerBuildRequestV1]" +$SqlRecords = Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $SqlQuery -Credential $Secret:sql_itdpsu1 -Verbose + + + +New-UDTable -Dense -ShowPagination -PageSize 20 -Size small -Data ($SqlRecords | Sort-Object -Descending opened_at) -Columns @( + New-UDTableColumn -Property 'NewSP' -Title 'New' -Render { + New-UDButton -Id "btnNewSP$($EventData.host_name)" -Text "New" -Color Secondary -Size small -OnClick { + Show-UDToast -Message ("Creating new record " + $EventData.host_name) -Duration 5000 + switch($EventData.request_type){ + 'New' { + $Fqdn = $EventData.host_name + $RitmNum = $EventData.RitmNum + + Invoke-PSUScript -Script 'New-ITDVMwareSharePointVMRecordFromRITM.ps1' -Fqdn $Fqdn -RitmNum $RitmNum + } + 'Removal' { + $Fqdn = $EventData.host_name + $RitmNum = $EventData.RitmNum + + } + } + + } + } + New-UDTableColumn -Property 'SyncSP' -Title 'SyncVCtoSP' -Render { + New-UDButton -Id "btnSyncSP$($EventData.host_name)" -Text "Sync" -Color primary -Size small -OnClick { + Show-UDToast -Message ("Sync to SharePoint - " + $EventData.host_name) -Duration 5000 + switch($EventData.request_type){ + 'Change' { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $EventData.RitmNum -IncludeVariableSet + ForEach($row in $Ritm.VariableSet){ + $Cmdb_Ci = Get-ITDServiceNowRecord -Table 'cmdb_ci_server' -SysId $row.host_name_ref + If ($Cmdb_Ci.name.display_value -eq $EventData.host_name){ + $Fqdn = $Cmdb_Ci.fqdn.display_value + } + } + Invoke-PSUScript -Script 'Sync-ITDVMwareVMMetadataToSharePoint.ps1' -VMName $Fqdn -Wait | Out-Null + } + 'New' { + $Fqdn = $EventData.host_name + } + } + + } + } + + New-UDTableColumn -Property "ImplSRM" -Title 'ImplSRMtoSP' -Render { + New-UDButton -Id "btnImplSRM$($EventData.host_name)" -Text "SRM" -Color secondary -Size small -OnClick { + Show-UDToast -Message ("Sync to SharePoint - " + $EventData.host_name) -Duration 5000 + switch($EventData.request_type){ + 'Change' { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $EventData.RitmNum -IncludeVariableSet + ForEach($row in $Ritm.VariableSet){ + $Cmdb_Ci = Get-ITDServiceNowRecord -Table 'cmdb_ci_server' -SysId $row.host_name_ref + If ($Cmdb_Ci.name.display_value -eq $EventData.host_name){ + $Fqdn = $Cmdb_Ci.fqdn.display_value + } + } + } + 'New' { + $Fqdn = $EventData.host_name + } + } + Invoke-PSUScript -Script 'Sync-ITDVMwareVMMetadataToSharePoint.ps1' -VMName $Fqdn -SRMImplemented -Wait | Out-Null + } + } + + + New-UDTableColumn -Property 'RitmUrl' -Title 'RitmUrl' -Render { + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=sc_req_item.do?sys_id=" + $EventData.RitmSysId) -Id "lnkRitm" -Content { + New-UDImage -Url "https://psuniversal.nd.gov/PSUniversal_Extras/servicenow_logo_icon_168835.png" -Height 20 -Width 20 + } + } + + New-UDTableColumn -Property 'RitmNum' -Title 'RitmNum' -ShowFilter + New-UDTableColumn -Property 'opened_at' -Title 'opened_at' -ShowFilter + New-UDTableColumn -Property 'host_name' -Title 'host_name' -ShowFilter + New-UDTableColumn -Property 'requested_for' -Title 'requested_for' -ShowFilter + New-UDTableColumn -Property 'request_type' -Title 'request_type' -ShowFilter + New-UDTableColumn -Property 'environment' -Title 'environment' -ShowFilter + #New-UDTableColumn -Property 'additional_comments' -Title 'additional_comments' -ShowFilter +) +} -Icon @{ + id = '7d67b921-68aa-4085-84e8-025e92671771' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/SpCmdbCompare.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/SpCmdbCompare.ps1 new file mode 100644 index 0000000..5bb00cc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/ServiceNowDumps/pages/SpCmdbCompare.ps1 @@ -0,0 +1,73 @@ +New-UDPage -Url "/SpCmdbCompare" -Name "SpCmdbCompare" -Content { +# Use Get-UDPage -Name 'SpCmdbCompare' to use this page in your dashboard +## + +New-UDForm -Content { + New-UDTypography -Text 'Enter FQDN to Compare' + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Id 'VMName' + } + } +} -OnValidate { + $FormContent = $EventData + if ($FormContent.VMName -eq $null -or $FormContent.VMName -eq '') { + New-UDFormValidationResult -ValidationError "VMName is required" + } + else { + New-UDFormValidationResult -Valid + } +} -OnSubmit { + New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred + #Invoke-PSUScript -Script 'Sync-ITDVMwareVMMetadataToSharePoint.ps1' -VMName $EventData.VMName -Wait | Out-Null + $SPItem = Get-ITDVMwareSharePointVMGuestList -Credential $Secret:ndgov_svcitdiaassprw | Where-Object Title -eq $EventData.VMName + $Hostname = $SPItem.Title.split('.')[0] + $Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName" + + New-UDLink -Url ("https://northdakota.service-now.com/nav_to.do?uri=" + $Cmdb.sys_class_name.value + ".do?sys_id=" + $Cmdb.sys_id.value) -Id "lnkCmdbCi" -Text "Open Cmdb Record" + New-UDLink -Url ("https://northdakota.service-now.com/now/nav/ui/classic/params/target/cmdb_ci_server_list.do%3Fsysparm_query%3DnameSTARTSWITH$HostName") -Text "Open Cmdb Table View" + + New-UDTypography -Text "SpTitle and Cmdb HostName" -Variant h5 + New-UDTextBox -Id SpTitle -Value $SPItem.Title + New-UDTextBox -Id SpTitle -Value $Cmdb.name.display_value + + New-UDTypography -Text "Environment" -Variant h5 + New-UDButton -Id "btnEnvironment" -Text "Push Environment to Cmdb" -Color Secondary -Size small -OnClick { + Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Cmdb.sys_id.value -Values @{environment = $SPItem.Environment} + } + New-UDTextBox -Id SpTitle -Value $SPItem.Environment + New-UDTextBox -Id SpTitle -Value $Cmdb.environment.display_value + + New-UDTypography -Text "AppName" -Variant h5 + New-UDButton -Id "btnAppName" -Text "Push AppName to Cmdb" -Color Secondary -Size small -OnClick { + Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Cmdb.sys_id.value -Values @{u_nd_application_svc = $SPItem.AppName} + } + New-UDTextBox -Id SpTitle -Value $SPItem.AppName + New-UDTextBox -Id SpTitle -Value $Cmdb.u_nd_application_svc.display_value + + New-UDTypography -Text "LicensingRestrictions" -Variant h5 + New-UDButton -Id "btnLicesning" -Text "Push Licensing to Cmdb" -Color Secondary -Size small -OnClick { + Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Cmdb.sys_id.value -Values @{u_nd_licensing_restrictions = $SPItem.LicensingRestrictions} + } + New-UDTextBox -Id SpTitle -Value $SPItem.LicensingRestrictions + New-UDTextBox -Id SpTitle -Value $Cmdb.u_nd_licensing_restrictions.display_value + + New-UDTypography -Text "DR_Protection" -Variant h5 + New-UDButton -Id "btnDRProtection" -Text "Push DR_Protection to Cmdb" -Color Secondary -Size small -OnClick { + Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Cmdb.sys_id.value -Values @{u_nd_dr_protection = $SPItem.DR_Protection} + } + New-UDTextBox -Id SpTitle -Value $SPItem.DR_Protection + New-UDTextBox -Id SpTitle -Value $Cmdb.u_nd_dr_protection.display_value + + New-UDTypography -Text "SRM Recovery Type" -Variant h5 + New-UDButton -Id "btnSRMRecoveryType" -Text "Push SRM Recovery Type to Cmdb" -Color Secondary -Size small -OnClick { + Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Cmdb.sys_id.value -Values @{u_srm_recovery_type = $SPItem.SRM_RecoveryVMtype} + } + New-UDTextBox -Id SpTitle -Value $SPItem.SRM_RecoveryVMtype + New-UDTextBox -Id SpTitle -Value $Cmdb.u_srm_recovery_type.display_value + +} +} -Title "SpCmdbCompare" -Icon @{ + id = '1d8ccbbe-f274-4e34-bc59-6ed19e2dfa0e' + type = 'icon' + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/SyncTest.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/SyncTest.ps1 new file mode 100644 index 0000000..690ff2c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/SyncTest.ps1 @@ -0,0 +1,3 @@ +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncTest/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/SyncVMwareVMtoSharePoint.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/SyncVMwareVMtoSharePoint.ps1 new file mode 100644 index 0000000..5e97f02 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/SyncVMwareVMtoSharePoint.ps1 @@ -0,0 +1,29 @@ +New-UDApp -Title 'SyncVMwareVMtoSharePoint' -Pages @( + New-UDPage -Name "Home" -Content { + New-UDForm -Content { + New-UDTypography -Text 'Enter a VMware VM name below and click the Submit button' + New-UDRow -Columns { + New-UDColumn -SmallSize 6 -LargeSize 6 -Content { + New-UDTextbox -Id 'VMName' + } + } + } -OnValidate { + $FormContent = $EventData + + if ($FormContent.VMName -eq $null -or $FormContent.VMName -eq '') { + New-UDFormValidationResult -ValidationError "VMName is required" + } else { + New-UDFormValidationResult -Valid + } + } -OnSubmit { + Show-UDToast -Message ($EventData.VMName + " sync in progress.") -Duration 5000 + + Invoke-PSUScript -Script 'Sync-ITDVMwareVMMetadataToSharePoint_script.ps1' -VMName $EventData.VMName -Wait | Out-Null + + Show-UDToast -Message ($EventData.VMName + " sync finished.") -Duration 10000 + } -OnProcessing { + New-UDTypography -Text ("Syncing " + $EventData.VMName + " ...") + New-UDProgress + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/pages/home.ps1 new file mode 100644 index 0000000..0ac2f51 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/SyncVMwareVMtoSharePoint/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' -Id 'homeText' +} -Generated \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/TestMultiPage.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/TestMultiPage.ps1 new file mode 100644 index 0000000..3c1ab69 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/TestMultiPage.ps1 @@ -0,0 +1,17 @@ +$Navigation = @( + New-UDListItem -Label 'Home' -Icon (New-UDIcon -Icon Home) -OnClick { + Invoke-UDRedirect -Url '/home' + } + New-UDListItem -Label 'Users' -Icon (New-UDIcon -Icon User) -OnClick { + Invoke-UDRedirect -Url '/users' + } + New-UDListItem -Label 'Groups' -Icon (New-UDIcon -Icon Users) -OnClick { + Invoke-UDRedirect -Url '/groups' + } +) + +New-UDApp -Title 'PowerShell Universal' -Pages @( + Get-UDPage -Name 'home' + Get-UDPage -Name 'users' + Get-UDPage -Name 'groups' +) -Navigation $Navigation \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/groups.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/groups.ps1 new file mode 100644 index 0000000..224a210 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/groups.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Groups' -Content { + New-UDTypography -Text 'Groups' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/home.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/home.ps1 new file mode 100644 index 0000000..f8ef4cd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/home.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Home' -Content { + New-UDTypography -Text 'Home' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/users.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/users.ps1 new file mode 100644 index 0000000..1be780a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Test/dashboards/TestMultiPage/pages/users.ps1 @@ -0,0 +1,3 @@ +New-UDPage -Name 'Users' -Content { + New-UDTypography -Text 'Users' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/authentication.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/authentication.ps1 new file mode 100644 index 0000000..8bf6128 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/authentication.ps1 @@ -0,0 +1,89 @@ +Set-PSUAuthenticationMethod -Type "Form" -ScriptBlock { + param( + [PSCredential]$Credential + ) + + Add-Type -AssemblyName System.DirectoryServices.AccountManagement + + # is this a UPN? + if ( $Credential.UserName.IndexOf('@') -gt -1 ) { + + # juggle back and forth from SID to get NTAccount format + $NTAccountName = ([System.Security.Principal.NTAccount]$Credential.UserName).Translate([System.Security.Principal.SecurityIdentifier]).Translate([System.Security.Principal.NTAccount]).Value + + } + elseif ( $Credential.UserName.IndexOf('\') -gt -1 ) { + + # already NTAccount format + $NTAccountName = $Credential.UserName + + } + else { + + # someone didn't enter their domain... + $NTAccountName = "NDGOV\" + $Credential.GetNetworkCredential().UserName + + } + + # split domain and username + $DomainName, $UserName = $NTAccountName.Split('\', 2) + + # perform auth with AD + $PrincipalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( 'Domain', $DomainName ) + $Authenticated = $PrincipalContext.ValidateCredentials( $UserName, $Credential.GetNetworkCredential().Password, 'Negotiate, Sealing' ) + + if ( $Authenticated ) { + + # discover the user principal, needed for the user DN + $UserPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $NTAccountName ) + + # get the user's domain + $UserDomainContext = [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new( 'Domain', $DomainName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) + $UserDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain( $UserDomainContext ) + + # get the computer's domain + #$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() + + # hold all the user groups + [System.Collections.Generic.List[hashtable]]$Groups = @() + + # get groups from user's domain + #[adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName)))", @('name') ).FindAll().ForEach({ + [adsisearcher]::new( $UserDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$($UserPrincipal.DistinguishedName))(name=ITD-PSUniversal-*))", @('name') ).FindAll().ForEach({ + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $UserDomain.Name + }) + }) + <# + # get groups from the computer's domain (if different) + if ( $UserDomain.Name -ne $ComputerDomain.Name ) { + + # lookup the user's foreign security principal in the computer's domain + $ForeignSecurityPrincipal = [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=foreignSecurityPrincipal)(objectClass=foreignSecurityPrincipal)(name=$($UserPrincipal.Sid)))", @('distinguishedName') ).FindOne().Properties['distinguishedName'][0] + + # find all the group memberships + [adsisearcher]::new( $ComputerDomain.GetDirectoryEntry(), "(&(objectCategory=group)(objectClass=group)(member:1.2.840.113556.1.4.1941:=$ForeignSecurityPrincipal))", @('name') ).FindAll().ForEach({ + + $Groups.Add(@{ + Type = 'Group' + Value = $_.Properties['name'][0] + Issuer = $ComputerDomain.Name + }) + + }) + + } + #> + New-PSUAuthenticationResult -Success -UserName $UserPrincipal.UserPrincipalName -Claims { + $Groups | ForEach-Object { New-PSUAuthorizationClaim @_ } + } + + } + else { + + New-PSUAuthenticationResult -ErrorMessage 'Bad username or password :)' + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/roles.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/roles.ps1 new file mode 100644 index 0000000..6f60cc3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/roles.ps1 @@ -0,0 +1,75 @@ +New-PSURole -Name "Administrator" -Description "Administrators can manage settings, create and edit any entity and view all the entities with PowerShell Universal." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains 'ITD-PSUniversal-Admin' +} +New-PSURole -Name "Execute" -Description "Execute scripts within PowerShell Universal." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + $false +} +New-PSURole -Name "Operator" -Description "Operators have access to manage and execute scripts, create other entities within PowerShell Universal but cannot manage PowerShell Universal itself." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + $false +} +New-PSURole -Name "Reader" -Description "Readers have read-only access to PowerShell Universal. They cannot make changes to any entity within the system." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + $true #default $false +} +New-PSURole -Name "Team-Windows" -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + #$false + $Roles = $User.Claims | Where-Object Type -EQ Group | Select-Object -ExpandProperty Value + $Roles -contains "ITD-PSUniversal-Team-Windows" +} +New-PSURole -Name "User" -Description "Does not have access to the admin console but can be assigned resources like APIs, scripts, dashboards and pages." -Policy { + param( + [Security.ClaimsPrincipal]$User + ) + + <# + Policies should return $true or $false to determine whether the user has the particular + claim that require them for that role. +#> + + $false +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/scripts.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/scripts.ps1 new file mode 100644 index 0000000..5368be7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/scripts.ps1 @@ -0,0 +1,4 @@ +New-PSUScript -Name "Get-HelloWorld.ps1" -Description "Get-HelloWorld.ps1" -Path "ZM-Test\Get-HelloWorld.ps1" +New-PSUScript -Name "NewITDVMwareVMSnapshotTask.ps1" -Description "NewITDVMwareVMSnapshotTask.ps1" -Path "Infra-VMware.Snapshot\NewITDVMwareVMSnapshotTask.ps1" +New-PSUScript -Name "Remove_ITDVmwareVMSnapshotExpired.ps1" -Description "Remove_ITDVmwareVMSnapshotExpired.ps1" -Path "Infra-VMware.Snapshot\Remove_ITDVmwareVMSnapshotExpired.ps1" +New-PSUScript -Name "Update-ITDVMwareVMSnapshotStatus.ps1" -Description "Update-ITDVMwareVMSnapshotStatus.ps1" -Path "Infra-VMware.Snapshot\Update-ITDVMwareVMSnapshotStatus.ps1" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/settings.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/settings.ps1 new file mode 100644 index 0000000..61a8794 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/settings.ps1 @@ -0,0 +1,5 @@ +$Parameters = @{ + EnhancedAppTokenSecurity = $true + ApiSecurityModel = "Medium" +} +Set-PSUSetting @Parameters \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/variables.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/variables.ps1 new file mode 100644 index 0000000..709ab6c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/.universal/variables.ps1 @@ -0,0 +1,2 @@ +New-PSUVariable -Name "ndgov_svcitdiaasauto" -Vault "Database" -Type "PSCredential" +New-PSUVariable -Name "ndgov_svcitdvmsnapmgr" -Vault "Database" -Type "PSCredential" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/NewITDVMwareVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/NewITDVMwareVMSnapshotTask.ps1 new file mode 100644 index 0000000..71ac391 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/NewITDVMwareVMSnapshotTask.ps1 @@ -0,0 +1,37 @@ +<##### +.SYNOPSIS + Creates a vCenter scheduled task that will create a virtual machine snapshot. +.DESCRIPTION + Creates a vCenter scheduled task that will create a virtual machine snapshot. 2506091114 +.NOTES + +.LINK + https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0017146 +#> + +[CmdletBinding()] +param ( + [Parameter( + Mandatory = $true, + HelpMessage = "The VMware virtual machine name. This is most commonly the FQDN. You can verify the virtual machine name by logging into vCenter. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back." + )] + [string[]] + $VMName = $null, + + [Parameter(Mandatory = $true, + HelpMessage = "The DateTime you want the snapshot to occur.")] + [datetime] + $DateTime = (Get-Date), + + [Parameter(Mandatory = $true, + HelpMessage = "How many hours the snapshot will exist. The snapshot will be automatically deleted after the duration. Maximum value is 72 hours.")] + [ValidateRange(1, 72)] + [int] + $DurationHours = 4, + + [Parameter(HelpMessage = "Email address that you want vCenter to notify when the snapshot is taken. Multiple entries can be submitted if the field loses focus, and you go back to it. For example, after each entry hit Tab, then Shift-Tab back.")] + [string[]] + $Email = $null +) + +Write-Warning -Message ("Creating new snapshot " + (Get-Date) ) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Remove_ITDVmwareVMSnapshotExpired.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Remove_ITDVmwareVMSnapshotExpired.ps1 new file mode 100644 index 0000000..d7b62a0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Remove_ITDVmwareVMSnapshotExpired.ps1 @@ -0,0 +1 @@ +# Script contents \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 new file mode 100644 index 0000000..d7b62a0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/Infra-VMware.Snapshot/Update-ITDVMwareVMSnapshotStatus.ps1 @@ -0,0 +1 @@ +# Script contents \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/ZM-Test/Get-HelloWorld.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/ZM-Test/Get-HelloWorld.ps1 new file mode 100644 index 0000000..8f3cb07 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal/ZM-Test/Get-HelloWorld.ps1 @@ -0,0 +1,3 @@ +# Script contents + +wtf \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/azure-pipelines.yml new file mode 100644 index 0000000..73af856 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-VMware.Administration' + +variables: + major: 2 + minor: 0 + 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.Infra-VMware.Administration.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.Infra-VMware.Administration.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/build.ps1 new file mode 100644 index 0000000..cd44750 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-VMware.Administration' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-VMware.Administration).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Helpers/ITD.Infra-VMware.Administration.old b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Helpers/ITD.Infra-VMware.Administration.old new file mode 100644 index 0000000..d8439da --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Helpers/ITD.Infra-VMware.Administration.old @@ -0,0 +1,688 @@ + + +<# +.Synopsis + Changes Portgroup on all NICs on specified VMs +.EXAMPLE + Set-ITDVMwareVMNicPortGroup -Computer itdsrv1.nd.gov -Vlan 1394 -Credential $AdminCred +#> +function Set-ITDVMwareVMNicPortGroup { + [CmdletBinding()] + Param + ( + [Parameter(Mandatory = $true)] + [string[]] + $ComputerName, + + [Parameter(Mandatory = $true)] + [int] + $Vlan, + + [PSCredential] + $Credential + ) + + Begin { + Connect-ITDvCenter -Credential $Credential + + Write-Verbose "Connected to: $global:DefaultVIServers" + If ($global:DefaultVIServers.Count -gt 0) { + Write-Verbose "connected to VI server(s)" + } + Else { + Write-Warning "not connected to any VIservers, stopping script" + break + break + } + + $AvailablePortGroup = Get-VirtualPortGroup -WarningAction SilentlyContinue + } + Process { + ForEach ($c in $ComputerName) { + Write-Verbose "[$c]:Start" + $CurrentVM = $null + $CurrentVMs = $null + $Datacenter1 = $null + $Datacenter2 = $null + $DestinationFolder = $null + $CurrentDatacenter = $null + + $CurrentVMs = Get-VM -Name $c -ErrorAction SilentlyContinue + + If ($CurrentVMs.Count -lt 1) { + Write-Warning "[$c]:VM name not found, please check it and try again ******" + } + Else { + If ($CurrentVMs.Count -gt 2) { + Write-Warning "[$c]:More than two results found, process this VM manually" + } + Else { + If ($CurrentVMs.Count -eq 2) { + Write-Verbose "[$c]:Two results found" + $Datacenter1 = ($CurrentVMs[0] | Get-Datacenter).Name + $Datacenter2 = ($CurrentVMs[1] | Get-Datacenter).Name + + Write-Verbose "[$c]:Check for SRM" + If ( ( ($Datacenter1 -eq "Primary Datacenter") -or ($Datacenter2 -eq "Primary Datacenter") ) -and ( ($Datacenter1 -eq "Secondary Datacenter") -or ($Datacenter2 -eq "Secondary Datacenter") ) ) { + Write-Warning "[$c]:One result in both Primary and Secondary Datacenters, assuming SRM and continuing" + If ($Datacenter1 -eq "Primary Datacenter") { + $CurrentVM = $CurrentVMs[0] + } + If ($Datacenter2 -eq "Primary Datacenter") { + $CurrentVM = $CurrentVMs[1] + } + } + Else { + Write-Warning "[$c]:Exactly two results in the same datacenter... Congratulations, you've acheieved the impossible." + break + } + } + Else { + Write-Verbose "[$c]:One match found" + $CurrentVM = $CurrentVMs + } + + If ($CurrentVM) { + $CurrentDatacenter = ($CurrentVM | Get-Datacenter).Name + Switch ($CurrentDatacenter) { + "Primary Datacenter" { + $VirtualSwitch = "PDC" + } + "Secondary Datacenter" { + $VirtualSwitch = "SDC" + } + } + + + $VLANsearch = '_' + $VLAN + $VMVLAN = $AvailablePortGroup | ` + Where-Object { $_.Name -Like "*$VLANsearch" -and $_.VirtualSwitch -like "*$VirtualSwitch*" } + $CurrentVM | Get-NetworkAdapter | ` + Set-NetworkAdapter -NetworkName $VMVLAN -Confirm:$false -RunAsync + } + } + } + Write-Verbose "[$c]:End Remove" + } + } + End { + } +} + + +<# +.Synopsis + Creates new distributed virtual port group with name standard +.DESCRIPTION + Long description +.EXAMPLE + New-ITDVMwarePortGroup -CIDR 10.2.60.0/23 -VLAN 1394 +.EXAMPLE + New-ITDVMwarePortGroup -CIDR 10.2.60.0/23 -VLAN 1394 -Credential $Credential +#> +function New-ITDVMwarePortGroup { + [CmdletBinding()] + Param + ( + [string] + $CIDR, + + [int] + $VLAN, + + [PSCredential] + $Credential + ) + + Begin { + Connect-ITDvCenter -Credential $Credential + $BismarckVDSwitch = 'dvSwitch-PDC-Data' + $MandanVDSwitch = 'dvSwitch-SDC-Data' + $IP = $CIDR.split('/')[0] + $Mask = $CIDR.split('/')[1] + $VLANstring = $VLAN.ToString('0000') + } + Process { + #$PGName="dvPG-$CIDR" + "_" + "$VLAN" + $PGName = "dvPG_" + $VLANstring + "_" + $IP + "_" + $Mask + Get-VDSwitch -Name $BismarckVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VLAN + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false + + Get-VDSwitch -Name $MandanVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VLAN + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false + } + End { + } +} + + +function Find-ITDVMDatastoreClusterMaxAverageDatastoreFreeSpace ($Cluster) { + $MaxDsCFreeSpaceAvgPerDiskGB = $null + $MaxDsCName = $null + + $AvailableDsC = Get-DatastoreCluster | Where-Object Name -Like *$Cluster* + $AvailableDsCCount = ($AvailableDsC | Measure-Object).Count + Write-Verbose "Found $AvailableDsCCount datastore clusters matching $Cluster" + + ForEach ($d in $AvailableDsC) { + $DsCFreeSpaceInfo = Get-DatastoreCluster -Name $d.Name | Get-Datastore | Select-Object FreeSpaceGB | Measure-Object -Property FreeSpaceGB -Average -Sum + $CurrentDsCFreeSpaceAvgPerDiskGB = $DsCFreeSpaceInfo.Average + + # If first in datastore clusters to check + If ($MaxDsCFreeSpaceAvgPerDiskGB -eq $null) { + Write-Verbose "First datastore cluster, default max datastore cluster" + $MaxDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB + $MaxDsCName = $d.Name + } + + # Is current Ds cluster avg free space per datastore is larger than max + If ($CurrentDsCFreeSpaceAvgPerDiskGB -gt $MaxDsCFreeSpaceAvgPerDiskGB) { + Write-Verbose "Current larger than Max" + $MaxDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB + $MaxDsCName = $d.Name + } + + Write-Verbose "CurrentDsCName: $d" + Write-Verbose "CurrentDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB" + Write-Verbose "MaxDsCFreeSpaceAvgPerDiskGB = $MaxDsCFreeSpaceAvgPerDiskGB" + } + + Write-Verbose "Return MaxDsCFreeSpaceName: $MaxDsCName" + return $MaxDsCName +} + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMWare-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL + Method = "Get" + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + #$List = (Invoke-WebRequest -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +function Get-ITDVMwareSharePointSnapshotRequestListTst { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMWare-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL + Method = "Get" + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + #$List = (Invoke-WebRequest -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +<# +.SYNOPSIS + Runs Unmap cmds from VMhost to cleanup dirty data blocks on A9K storage +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Start-ITDVMwareDatastoreUnmap { + [CmdletBinding()] + param + ( + [string[]] + $Datastore, + + [PSCredential] + $Credential + ) + + begin { + $ConnectITDvCenterParams = @{ } + If ($Credential) { $ConnectITDvCenterParams += @{Credential = $Credential } } + Connect-ITDvCenter @ConnectITDvCenterParams + } + + process { + $Clusters = Get-Datacenter Secondary*, Primary* | Get-Cluster + ForEach ($Cluster in $Clusters) { + $esxcli = $null + $Datastores = $null + $VMHost = $null + + $Datastores = $Cluster | Get-Datastore | Where-Object { $_.Name -notlike "*TEMPL*" -and $_.Name -like "*$Datastore*" -and $_.Name -like "*A9K*" } | Sort-Object Name + $VMHost = $Cluster | Get-VMHost | Where-Object ConnectionState -EQ "Connected" | Select-Object -First 1 + $esxcli = Get-EsxCli -VMHost $VMHost + + ForEach ($ds in $Datastores) { + $TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$ds]:Start $TimeStamp on $VMHost" + + $esxcli.storage.vmfs.unmap($null, $ds, $null) + } + } + } + + end { + } +} + + + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Remove-ITDVMwareDatastoreStep1 { + [CmdletBinding()] + Param + ( + [int[]] + $LunId, + + [PSCredential] + $vCenterCredential, + + [PSCredential] + $SharePointCredential + ) + + begin { + $ConnectITDvCenterParams = @{ } + If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } } + Connect-ITDvCenter @ConnectITDvCenterParams + $VMwareList = Get-Datastore + + $GetITDVMwareSharePointDatastoreRecordParams = @{ } + If ($SharePointCredential) { $GetITDVMwareSharePointDatastoreRecordParams = @{Credential = $SharePointCredential } } + #$SharePointList = Get-ITDVMwareSharePointDatastoreRecord | select *,@{n='Name';e={$_.Title}} + $SharePointList = Get-ITDVMwareSharePointDatastoreRecord @GetITDVMwareSharePointDatastoreRecordParams | Select-Object *, @{n = 'Name'; e = { $_.Title } } + } + + process { + $DatastoreRemovalSuccess = @() + $DatastoreRemovalFailure = @() + + ForEach ($Id in $LunId) { + $DatastoreID = $null + $Datastore = $null + + $Datastores = Get-Datastore | Where-Object Name -Like ("*_" + $Id + "_*") + ForEach ($Datastore in $Datastores) { + $SharePointRecord = $null + + $DatastoreHosts = $Datastore | Get-VMHost + $VMHostCanonicalName = (Get-ScsiLun -VmHost ($DatastoreHosts | Select-Object -First 1) | Where-Object RuntimeName -Like "*L$Id*").CanonicalName + $SharePointRecord = ($SharePointList | Where-Object Title -EQ $Datastore.Name) + + If ($SharePointRecord.ExtentName -eq $VMHostCanonicalName) { + Write-Verbose ($Datastore.Name + " *** " + $VMHostCanonicalName + " *** CanonicalName accurate in SharePoint, continuing with unmount") + + try { + Get-Datastore $Datastore #| Unmount-Datastore + $DatastoreHosts | Select-Object -First 1 | Remove-Datastore $Datastore -Confirm:$false -RunAsync + $DatastoreRemovalSuccess += $Datastore.Name + } + catch { + $DatastoreRemovalFailure += $Datastore.Name + } + } + else { + Write-Error ($Datastore.Name + " *** " + " *** CanonicalName mismatch with SharePoint Record") + } + } + } + } + + end { + + } +} + +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Remove-ITDVMwareDatastoreStep3 { + [CmdletBinding()] + Param + ( + [int[]] + $LunId, + + [PSCredential] + $vCenterCredential, + + [PSCredential] + $SharePointCredential + ) + + begin { + $ConnectITDvCenterParams = @{ } + If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } } + Connect-ITDvCenter @ConnectITDvCenterParams + $VMwareList = Get-Datastore + + $GetITDVMwareSharePointDatastoreRecordParams = @{ } + If ($SharePointCredential) { $GetITDVMwareSharePointDatastoreRecordParams = @{Credential = $SharePointCredential } } + #$SharePointList = Get-ITDVMwareSharePointDatastoreRecord | select *,@{n='Name';e={$_.Title}} + $SharePointList = Get-ITDVMwareSharePointDatastoreRecord @GetITDVMwareSharePointDatastoreRecordParams | Select-Object *, @{n = 'Name'; e = { $_.Title } } + } + + process { + $DeviceUidToRemove = @() + ForEach ($Id in $LunId) { + $DeviceUidToRemove += $SharePointList | Where-Object Name -Like "*$Id*" | Select-Object *, @{n = 'HostCluster'; e = { $_.Name.split('_')[0] -replace "VM" } } + } + $DeviceUidToRemove = $DeviceUidToRemove | Sort-Object HostCluster + + If (@($DeviceUidToRemove).count -ne @($LunId).count) { Write-Error "LunId and datastore search count mismatch, verify SharePoint manually before continuing" } + else { + + #confirmation prompt + Write-Warning "The following SAN volumes will be detached from the VMware hosts. Please confirm this list is correct:" + $DeviceUidToRemove | ForEach-Object { Write-Warning ($_.Name + " *** " + $_.ExtentName) } + Pause + $HostClusters = $DeviceUidToRemove | Group-Object HostCluster + ForEach ($HostCluster in $HostClusters) { + $VMHosts = Get-Cluster $HostCluster.Name | Get-VMHost + + ForEach ($DeviceUid in @($DeviceUidToRemove | Where-Object HostCluster -EQ $HostCluster)) { + $removeUID = Get-ScsiLun -VmHost $VMHosts | Where-Object CanonicalName -EQ $DeviceUid | Select-Object -First 1 + If ($removeUID) { + foreach ($VMHost in $VMHosts) { + $esxcli = Get-EsxCli -VMHost $VMHost -V2 + #$esxcli.storage.core.device.detached.remove.invoke(@{device = $removeUID}) + } + } + } + Get-VMHostStorage -VMHost $VMhosts -RescanAllHba -RescanVmfs + } + } + } + + end { + + } +} + + +function Get-ITDVMwareAlarmState { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ParameterSetName = 'Entity' + )] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl] + $Entity, + + [switch] + $Recurse = $false + ) + + begin { + + } + + process { + $Entity = Get-Inventory -Id $Entity.Id + if ($Recurse) { + $VMObjects = @($Entity) + $VMObjects += Get-Inventory -Location $Entity + } + else { + $VMObjects = $Entity + } + $VMObjects | Select-Object Name, ` + @{N = "Type"; E = { $_.GetType().Name.Replace("Impl", "").Replace("Wrapper", "") } }, ` + @{N = "Alarm actions enabled"; E = { $_.ExtensionData.alarmActionsEnabled } } + } + + end { + + } +} + +function Set-ITDVMwareAlarmState { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl] + $Entity, + + [switch] + $Enabled, + + [switch] + $Recurse + ) + + begin { + $alarmMgr = Get-View AlarmManager + } + + process { + if ($Recurse) { + $VMObjects = @($Entity) + $VMObjects += Get-Inventory -Location $Entity + } + else { + $VMObjects = $Entity + } + + $VMObjects | ForEach-Object { + $alarmMgr.EnableAlarmActions($_.Extensiondata.MoRef, $Enabled) + } + } + + end { + + } +} + +function Expand-ITDVMwareDatastore { + param ( + [string[]] + $LunId + ) + + $HostsToRescan = @() + ForEach ($Id in $LunId) { + $Datastore = Get-Datastore "*$Id*" + $HostSystem = Get-View -Id ($Datastore.ExtensionData.Host | Select-Object -First 1 | Select-Object -ExpandProperty Key) + $DatastoreSystem = Get-View -Id $HostSystem.ConfigManager.DatastoreSystem + $ExpandOptions = $DatastoreSystem.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) + $DatastoreSystem.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef, $ExpandOptions.spec) + $HostsToRescan += $Datastore | Get-VMHost | Sort-Object Name + } +} + +function New-ITDVMwareHostScratchFolder { + [CmdletBinding()] + param ( + [ValidateSet("Bismarck", "Mandan")] + [string] + $Site, + + [string] + $VMHost + ) + Begin { + } + + Process { + switch ($Site) { + "Bismarck" { + $vCenter = "itdvmvc1.nd.gov@443" + $Datacenter = "Primary Datacenter" + $Datastore = "VMALL1_006_FS92_SCRATCH" + } + "Mandan" { + $vCenter = "itdvmvc2.nd.gov@443" + $Datacenter = "Secondary Datacenter" + $Datastore = "VMALL2_007_FS92_SCRATCH" + } + } + New-Item -Path "vmstores:\$vCenter\$Datacenter\$Datastore\scratch" -Name $VMHost -ItemType Directory + } + + End { + } +} + + +function Set-ITDVMwareHostMaintenance { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string[]] + $Name, + + [ValidateSet("Enter", "Exit")] + [string] + $Status + ) + Begin { + + } + Process { + ForEach ($n in $Name) { + $VMHost = $null + $VMHost = Get-VMHost $n + $alarmMgr = Get-View AlarmManager -Server $VIServer + + switch ($Status) { + "Enter" { + $VMHost | Set-VMHost -State "Maintenance" -RunAsync + $ViServer = $VMHost.Uid.split('@')[1].split(':')[0] + $alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $false) + } + "Exit" { + $VMHost | Set-VMHost -State "Connected" -RunAsync + $ViServer = $VMHost.Uid.split('@')[1].split(':')[0] + $alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $true) + } + } + + } + Get-VMHost $Name | Select-Object Name, ConnectionState, @{n = 'Alarms'; e = { $_.ExtensionData.AlarmActionsEnabled } } + } + + End { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.nuspec new file mode 100644 index 0000000..2733044 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.nuspec @@ -0,0 +1,9 @@ + + + + ITD.Infra-VMware.Administration + $VERSIONHERE$ + Zack Meier / Don Lange + Functions for VMware administration + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psd1 new file mode 100644 index 0000000..ebecb35 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psd1 @@ -0,0 +1,10 @@ +@{ + RootModule = 'ITD.Infra-VMware.Administration.psm1' + ModuleVersion = '' + GUID = 'b940f358-3867-4785-81d2-4bab53872613' + Author = 'Zack Meier / Don Lange ' + CompanyName = 'State of North Dakota' + PowerShellVersion = '5.1' + CompatiblePSEditions = 'Desktop','Core' + FunctionsToExport = @() +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/ITD.Infra-VMware.Administration.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Connect-ITDvCenter.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Connect-ITDvCenter.ps1 new file mode 100644 index 0000000..0586870 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Connect-ITDvCenter.ps1 @@ -0,0 +1,36 @@ +<# +.Synopsis + Connects to ITD's vCenter servers +.DESCRIPTION + Connects to ITD's vCenter servers +.EXAMPLE + Connect-ITDvCenter -Credential $PSCredential +#> +function Connect-ITDvCenter { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + Begin { + Import-Module VMware.VimAutomation.Core + $VIServers = "itdvmvc1.nd.gov", "itdvmvc2.nd.gov" + } + Process { + If ($Global:DefaultVIServers) { + Write-Verbose "VIServers already connected" + } + Else { + If ($Credential) { + Connect-VIServer -Server $VIServers -Credential $Credential | Out-Null + } + Else { + Connect-VIServer -Server $VIServers | Out-Null + } + } + } + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disable-ITDVMwareVMHostFeature.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disable-ITDVMwareVMHostFeature.ps1 new file mode 100644 index 0000000..b6cc655 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disable-ITDVMwareVMHostFeature.ps1 @@ -0,0 +1,57 @@ +<# +.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 Disable-ITDVMwareVMHostFeature { + [CmdletBinding()] + param ( + + [Parameter(Mandatory = $true)] + [string[]] + $Name, + + [switch] + $LockdownMode, + + [switch] + $SSH, + + [switch] + $AlarmActions + ) + Begin { + + } + Process { + $VMHosts = Get-VMHost -Name $Name + ForEach ($VMHost in $VMHosts) { + If ($LockdownMode) { + ($VMHost | Get-View).ExitLockdownMode() + } + If ($SSH) { + Get-VMHostService -VMHost $VMHost | Where-Object { $_.key -eq 'TSM-SSH' } | Stop-VMHostService -Confirm:$false | Select-Object VMHost, Key, Label, Running + } + If ($AlarmActions) { + $VIServer = $VMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $VMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $false) + } + } + } + } + End { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disconnect-ITDvCenter.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disconnect-ITDvCenter.ps1 new file mode 100644 index 0000000..e87a451 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Disconnect-ITDvCenter.ps1 @@ -0,0 +1,23 @@ +<# +.Synopsis + Disconnects from ITD's vCenter servers +.DESCRIPTION + Disconnects from ITD's vCenter servers +.EXAMPLE + Disconnect-ITDvCenter +#> +function Disconnect-ITDvCenter { + [CmdletBinding()] + Param + ( + ) + + Begin { + $VIServers = "itdvmvc1.nd.gov", "itdvmvc2.nd.gov" + } + Process { + Disconnect-VIServer -Server $VIServers -Confirm:$false + } + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Enable-ITDVMwareVMHostFeature.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Enable-ITDVMwareVMHostFeature.ps1 new file mode 100644 index 0000000..d73c0ba --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Enable-ITDVMwareVMHostFeature.ps1 @@ -0,0 +1,57 @@ +<# +.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 Enable-ITDVMwareVMHostFeature { + [CmdletBinding()] + param ( + + [Parameter(Mandatory = $true)] + [string[]] + $Name, + + [switch] + $LockdownMode, + + [switch] + $AlarmActions, + + [switch] + $SSH + ) + Begin { + + } + Process { + $VMHosts = Get-VMHost -Name $Name + ForEach ($VMHost in $VMHosts) { + If ($LockdownMode) { + ($VMHost | Get-View).EnterLockdownMode() + } + If ($SSH) { + Get-VMHostService -VMHost $VMHost | Where-Object { $_.key -eq 'TSM-SSH' } | Start-VMHostService -Confirm:$false | Select-Object VMHost, Key, Label, Running + } + If ($AlarmActions) { + $VIServer = $VMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $VMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false) { + $alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $true) + } + } + } + } + End { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDSRMReport.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDSRMReport.ps1 new file mode 100644 index 0000000..dabce7b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDSRMReport.ps1 @@ -0,0 +1,33 @@ +$PowerBi = Import-Csv -Path D:\Downloads\serverinventory20251002.csv +$SRM = Import-Csv -Path D:\Downloads\itdvmvc1.nd.gov-itdvmvc2.nd.gov-20251002-102657.csv +$VMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -eq "placeholderVm" } + +$Result = [System.Collections.ArrayList]@() +foreach ($pbi in $PowerBi) { + Write-Verbose -Message ($pbi.'Host Name') -Verbose + $obj = $null + + $obj = [PSCustomObject]@{ + PowerBi = $pbi.'Host Name' + Placeholder = $VMs | Where-Object Name -EQ $pbi.'Host Name' | Select-Object -ExpandProperty Name -First 1; + SRM = $SRM | Where-Object "Virtual Machine" -EQ $pbi.'Host Name' | Select-Object -ExpandProperty "Virtual Machine" + CMDB = ((Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("name=" + $pbi.'Host Name'.split('.')[0])).name.display_value) + } + $null = $Result.Add($obj) +} + +foreach ($VM in $VMs) { + if ($Result | Where-Object Placeholder -EQ $VM.Name) { + #do nothing + } + else { + Write-Verbose -Message ($VM.Name) -Verbose + $obj = [PSCustomObject]@{ + PowerBi = $PowerBi | Where-Object 'Host Name' -EQ $pbi.'Host Name' + Placeholder = $VM.Name; + SRM = $SRM | Where-Object "Virtual Machine" -EQ $pbi.'Host Name' + CMDB = ((Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("name=" + $pbi.'Host Name'.split('.')[0])).name.display_value); + } + $null = $Result.Add($obj) + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareDatastoreReport.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareDatastoreReport.ps1 new file mode 100644 index 0000000..059f1ef --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareDatastoreReport.ps1 @@ -0,0 +1,58 @@ +<# +.SYNOPSIS + Usage report for VMware datastores. +.DESCRIPTION + Usage report for VMware datastores. +.NOTES + Requires VMware PowerCLI module. + Requires connection to vCenter. +.EXAMPLE + Get-ITDVMwareDatastoreReport + Retrieves a report of all datastores in the vCenter. +.EXAMPLE + Get-ITDVMwareDatastoreReport -Name "*78*" + Retrieves a report of all datastores in the vCenter that match the name pattern "*78*". +.PARAMETER Name + The name of the datastore to retrieve. If not specified, all datastores will be returned. + Supports wildcards. +#> + +function Get-ITDVMwareDatastoreReport { + [CmdletBinding()] + param ( + [string] + $Name + ) + + begin { + + } + + process { + if ($PSBoundParameters.ContainsKey('Name')) { + $AllDatastores = Get-Datastore -Name $Name + } + else { + $AllDatastores = Get-Datastore + } + + foreach ($Datastore in $AllDatastores) { + $FreeSpaceGB = $Datastore.FreeSpaceGB + $CapacityGB = $Datastore.CapacityGB + $UsedSpaceGB = $CapacityGB - $FreeSpaceGB + $obj = [PSCustomObject]@{ + Name = $Datastore.Name; + Datacenter = $Datastore.Datacenter.Name + FreeSpaceGB = $FreeSpaceGB; + UsedSpaceGB = ($CapacityGB - $FreeSpaceGB); + CapacityGB = $CapacityGB; + FreePercent = [math]::round($Datastore.FreeSpaceGB / $Datastore.CapacityGB * 100, 2); + } + #$null = $Result.Add($obj) + Write-Output $obj + } + } + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareSRMUsage.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareSRMUsage.ps1 new file mode 100644 index 0000000..40a9c22 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareSRMUsage.ps1 @@ -0,0 +1,73 @@ +# servicenow cmdb ci dr protection +# vcenter placeholder + +$AllVMwareVMs = Get-Datacenter | Where-Object {$_.Name -like "*Primary*" -or $_.Name -like "*Secondary*" -or $_.Name -like "*DCN*"} | Get-VM | Where-Object { $_.Name -notlike "vCLS*" } | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Sort-Object Name +$AllVMwarePlaceholders = $AllVMwareVMs | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -eq "placeholderVm" } +$AllCmdbCi = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "operational_status!=6^u_nd_dr_protectionLIKEVMware" -IncludeTotalCount | Select-Object @{n = 'CiName'; e = { $_.name.display_value } }, @{n = 'CiFqdn'; e = { $_.fqdn.display_value } }, @{n = 'CiOpStatus'; e = { $_.operational_status.display_value } }, @{n = 'DRProtection'; e = { $_.u_nd_dr_protection.display_value } } | Sort-Object CiName + +$ArrayList = [System.Collections.ArrayList]@() + +# check for placeholder +ForEach ($Ci in $AllCmdbCi) { + $PlaceholderBool = $null + $VMBool = $null + + If($AllVMwareVMs | Where-Object { $_.Name -eq $Ci.CiFqdn }) { + $VMBool = $true + } + else { + $VMBool = $false + } + + If ($AllVMwarePlaceholders | Where-Object { $_.Name -eq $Ci.CiFqdn }) { + $PlaceholderBool = $true + } + else { + $PlaceholderBool = $false + } + + $obj = [PSCustomObject]@{ + CiName = $Ci.CiName + CiFqdn = $Ci.CiFqdn + CiOpStatus = $Ci.CiOpStatus + DRProtection = $Ci.DRProtection + VMExists = $VMBool + Placeholder = $PlaceholderBool + } + + $null = $ArrayList.Add($obj) +} + +# verify no extra entries in vm list / confirm all vms have cmdb entries +ForEach ($VM in $AllVMwareVMs) { + If (-not ($ArrayList | Where-Object { $_.CiFqdn -eq $VM.Name })) { + #Write-Host "VM $($VM.Name) does not have a corresponding CMDB entry." -ForegroundColor Red + $obj = [PSCustomObject]@{ + CiName = $null + CiFqdn = $null + CiOpStatus = $null + DRProtection = $null + VMExists = $VM.Name + PlaceholderExists = $null + } + $null = $ArrayList.Add($obj) + } +} + +# verify no extra entries in placeholder list / confirm all placeholders have cmdb entries +ForEach ($Placeholder in $AllVMwarePlaceholders) { + If (-not ($ArrayList | Where-Object { $_.CiFqdn -eq $Placeholder.Name })) { + #Write-Host "Placeholder VM $($Placeholder.Name) does not have a corresponding CMDB entry." -ForegroundColor Red + $obj = [PSCustomObject]@{ + CiName = $null + CiFqdn = $Placeholder.Name + CiOpStatus = $null + DRProtection = $null + VMExists = $null + PlaceholderExists = $true + } + $null = $ArrayList.Add($obj) + } +} + +$ArrayList | Sort-Object CiFqdn | Format-Table -AutoSize \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHAEventList.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHAEventList.ps1 new file mode 100644 index 0000000..8983b54 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHAEventList.ps1 @@ -0,0 +1,42 @@ +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Get-ITDVMwareVMHAEventList { + [CmdletBinding()] + Param + ( + + ) + + begin { + + } + + process { + $Date = Get-Date + $HAVMrestartold = 5 + Get-VIEvent -MaxSamples 100000 -Start ($Date).AddDays(-$HAVMrestartold) -type warning | Where-Object { $_.FullFormattedMessage -match "restarted" } | Select-Object CreatedTime, ObjectName, FullFormattedMessage | Sort-Object CreatedTime -Descending + } + + end { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostHBA.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostHBA.ps1 new file mode 100644 index 0000000..a9bac13 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostHBA.ps1 @@ -0,0 +1,61 @@ +<# +.SYNOPSIS + Retrieves HBA (Host Bus Adapter) device information, including WWN (World Wide Name) and WWP (World Wide Port Name), for specified VMware ESXi hosts. + +.DESCRIPTION + This function connects to one or more VMware ESXi hosts and gathers detailed information about their HBA devices. The information collected includes the device name, WWN, WWP, and other relevant properties. This is useful for inventory, troubleshooting, or auditing storage connectivity in a VMware environment. + +.PARAMETER VMHost + Specifies the ESXi host(s) from which to retrieve HBA information. Accepts one or more host names or objects. + +.EXAMPLE + Get-ITDVMwareVMHostHBA -VMHost "esxi01.domain.local" + Retrieves HBA information from the specified ESXi host. + +.EXAMPLE + Get-ITDVMwareVMHostHBA + Retrieves HBA information from all connected ESXi hosts. +#> + +function Get-ITDVMwareVMHostHBA { + [CmdletBinding()] + param ( + [string] + $VMHostName + ) + + begin { + + } + + process { + If ($PSBoundParameters.ContainsKey('VMHostName')) { + $AllVMHosts = Get-VMHost -Name $VMHostName + } + Else { + $AllVMHosts = Get-VMHost + } + + ForEach ($VMHost in $AllVMHosts) { + $HBAs = $null + $HBAs = Get-VMHostHba -VMHost $VMHost -Type FibreChannel + ForEach ($HBA in $HBAs) { + $wwn = "{0:X}" -f $HBA.NodeWorldWideName + $wwp = "{0:X}" -f $HBA.PortWorldWideName + $obj = [PSCustomObject]@{ + 'VMHostName' = $VMHost.Name; + 'Device' = $HBA.Device; + 'Model' = $HBA.Model; + 'Status' = $HBA.Status; + 'NodeWorldWideName' = (0..7 | ForEach-Object { $wwn.Substring($_ * 2, 2) }) -join ':' + 'PortWorldWideName' = (0..7 | ForEach-Object { $wwp.Substring($_ * 2, 2) }) -join ':' + } + Write-Output $obj + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostStatus.ps1 new file mode 100644 index 0000000..a270440 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Get-ITDVMwareVMHostStatus.ps1 @@ -0,0 +1,41 @@ +<# +.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-ITDVMwareVMHostStatus { + [CmdletBinding()] + param ( + [string[]] + $Name + ) + Begin { + } + + Process { + If ($Name) { + Get-VMHost -Name $Name | Select-Object Name, ConnectionState, ` + @{n = 'AlarmActionsEnabled'; e = { $_.ExtensionData.AlarmActionsEnabled } }, ` + @{n = "LockdownMode"; e = { $_.ExtensionData.Config.LockdownMode } }, ` + @{n = 'TSM-SSH'; e = { ($_ | Get-VMHostService | Where-Object { $_.Key -eq "TSM-SSH" }).Running } } + } + Else { + Get-VMHost | Select-Object Name, ConnectionState, ` + @{n = 'AlarmActionsEnabled'; e = { $_.ExtensionData.AlarmActionsEnabled } }, ` + @{n = "LockdownMode"; e = { $_.ExtensionData.Config.LockdownMode } }, ` + @{n = 'TSM-SSH'; e = { ($_ | Get-VMHostService | Where-Object { $_.Key -eq "TSM-SSH" }).Running } } + } + } + + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/New-ITDVMNetwork.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/New-ITDVMNetwork.ps1 new file mode 100644 index 0000000..5c34043 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/New-ITDVMNetwork.ps1 @@ -0,0 +1,209 @@ +<# +.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-ITDVMNetwork { + [CmdletBinding()] + Param + ( + [Parameter(Mandatory = $true)] + [string] + $CIDR, + + [Parameter(Mandatory = $true)] + [ValidateLength(3, 4)] + [string] + $VlanId, + + [Parameter(Mandatory = $true)] + [ValidateSet("Data-Server", "Data-User")] + [string] + $DataType, + + #[PSCredential] + #$SharePointCredential, + + [PSCredential] + $vCenterCredential + ) + + begin { + If ($VlanId -eq "MAC" -or $VlanId -eq "MAG") { + $Hypervisor = "Azure" + } + Else { + $Hypervisor = "VMware" + } + Write-Verbose "Hypervisor $Hypervisor" + #VMware + If ($Hypervisor -eq "VMware") { + $ConnectITDvCenterParams = @{ } + If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } } + Connect-ITDvCenter @ConnectITDvCenterParams + + switch ($DataType) { + 'Data-Server' { + $BismarckVDSwitch = 'dvSwitch-PDC-Data-Server' + $MandanVDSwitch = 'dvSwitch-SDC-Data-Server' + } + 'Data-User' { + $BismarckVDSwitch = 'dvSwitch-PDC-Data-User' + $MandanVDSwitch = 'dvSwitch-SDC-Data-User' + } + } + + + $PortGroupList = Get-VirtualPortGroup + } + + <#SharePoint + $InvokeWebRequestParams = $null + If ($SharePointCredential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItems = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000' + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + } + #> + } + + process { + try { + <# + If ($SharePointCredential) { $GetITDVMwareSharePointNetworkListParams += @{Credential = $SharePointCredential } } + $NetworkList = Get-ITDVMwareSharePointNetworkList @GetITDVMwareSharePointNetworkListParams + #> + $NetworkId = $CIDR.split('/')[0] + $NetworkMask = $CIDR.split('/')[1] + + If ($VlanId -match "^\d+$" -and $VlanId.length -eq 3) { + $VlanId = "0" + $VlanId + } + + <# Verify CIDR not already in SharePoint + If (@($NetworkList | Where-Object CIDR -EQ $CIDR)) { + Write-Error "CIDR already exists in SharePoint" + } + #> + + # If VMware, do more checks then create port group + If ($Hypervisor -eq "VMware") { + # verify VlanId not already in sharepoint + If (@($NetworkList | Where-Object Vlan_Id -EQ $VlanId)) { + Write-Error "Vlan Id already exists in SharePoint" + Exit + } + + # verify Vlan Id not already in vmware portgroup + If (@($PortGrouplist | Where-Object { $_.Name.split('_')[2] -eq $NetworkId })) { + Write-Error "Network_Id already exists in VMware PortGroup name" + Exit + } + If (@($PortGrouplist | Where-Object { $_.Name.split('_')[1] -eq $VlanId } )) { + Write-Error "VlanId already exists in VMware PortGroup name" + Exit + } + + # Add new port group to VMware + $PGName = "dvPG_" + $VlanId + "_" + $NetworkId + "_" + $NetworkMask + + Get-VDSwitch -Name $BismarckVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VlanId + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDSecurityPolicy | Set-VDSecurityPolicy -MacChanges $false -AllowPromiscuous $false + + Get-VDSwitch -Name $MandanVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VlanId + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDSecurityPolicy | Set-VDSecurityPolicy -MacChanges $false -AllowPromiscuous $false + } + + # Get PA7050 Zone info + If ($Hypervisor -eq "Azure") { + $Secure = "True" + $PA_Zone = "Azure" + $AutoUpdate = $false + + } + If ($Hypervisor -eq "VMware") { + #$PAInterface = Get-ITDPAInterface -Number ($VlanId.TrimStart('0')) + #If (@($PAInterface).count -gt 1) { + # Write-Error "More than one PA Interface found" + # exit + #} + #else { + # $Secure = [string]$PAInterface.ZeroTrust + # $PA_Zone = $PAInterface.Zone + # $AutoUpdate = $true + #} + } + + <# Add to SharePoint + [PSCustomObject]$NewRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName } + } + $NewRecord += @{Title = ("new_" + $env:USERNAME) } + $NewRecord += @{CIDR = $CIDR } + $NewRecord += @{DataType = $DataType } + $NewRecord += @{Vlan_Id = $VlanId } + $NewRecord += @{PA_Zone = $PA_Zone } + $NewRecord += @{Secure = $Secure } + $NewRecord += @{AutoUpdate = $AutoUpdate } + $InvokeWebRequestParams = @{ + Uri = $UrlListItems; + Method = "Post"; + Body = $NewRecord | ConvertTo-Json; + ContentType = "application/json;odata=verbose"; + Headers = $Header; + UseBasicParsing = $AutoUpdate; + } + If ($SharePointCredential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + Invoke-RestMethod @InvokeWebRequestParams + #> + } + catch { + Write-Error $error[0] + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareCdDriveMedia.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareCdDriveMedia.ps1 new file mode 100644 index 0000000..30d9e87 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareCdDriveMedia.ps1 @@ -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 Remove-ITDVMwareCdDriveMedia { + [CmdletBinding()] + Param + ( + [string[]] + $ComputerName, + + [PSCredential] + $Credential + ) + + Begin { + Connect-ITDvCenter -Credential $Credential + Write-Verbose "Connected to: $global:DefaultVIServers" + If ($global:DefaultVIServers.Count -gt 0) { + Write-Verbose "connected to VI server(s)" + } + Else { + Write-Warning "not connected to any VIservers, stopping script" + break + break + } + } + Process { + ForEach ($c in $ComputerName) { + $CurrentVM = $null + + $CurrentVM = Get-VM -Name $c + $CurrentVM | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + } + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareOSCustomizationSpecOrphan.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareOSCustomizationSpecOrphan.ps1 new file mode 100644 index 0000000..406c0cc --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Remove-ITDVMwareOSCustomizationSpecOrphan.ps1 @@ -0,0 +1,34 @@ +<# +.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 Remove-ITDVMwareOSCustomizationSpecOrphan { + [CmdletBinding()] + param ( + [int] + $DaysToKeep = 60 + ) + + begin { + + } + + process { + $OSCustomizationSpecToRemove = Get-OSCustomizationSpec | Where-Object { $_.Name -like "AutoBuild-*" -and $_.LastUpdate -lt ((Get-Date).AddDays($DaysToKeep)) } + $OSCustomizationSpecToRemove | Remove-OSCustomizationSpec -Confirm:$false + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Set-ITDVMwareHostMaintenance.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Set-ITDVMwareHostMaintenance.ps1 new file mode 100644 index 0000000..5d9c251 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Public/Set-ITDVMwareHostMaintenance.ps1 @@ -0,0 +1,76 @@ +<# +.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 Set-ITDVMwareHostMaintenance { + [CmdletBinding()] + param ( + [Parameter(ParameterSetName = 'Enclosure', Mandatory = $true)] + [string] + $EnclosureName, + + [Parameter(ParameterSetName = 'Manual', Mandatory = $true)] + [string[]] + $VMHostName, + + [ValidateSet('Maintenance', 'Online', 'Connected')] + [string] + $State + ) + + begin { + + } + + process { + + switch ($PSCmdlet.ParameterSetName) { + 'Enclosure' { + Write-Verbose "Setting all VMHosts in enclosure $EnclosureName to $State mode." + try { + $VMHostName = (Get-OVServer | Where-Object Name -like $EnclosureName -ErrorAction Stop).ServerName + } + catch { + Write-Error "Failed to retrieve enclosure $EnclosureName. Error: $_" + throw + } + } + 'Manual' { + Write-Verbose "Setting specified VMHosts to $State mode." + } + } + + switch ($State) { + 'Maintenance' { + Write-Verbose "Setting VMHost $VMHostName to Maintenance mode." + try { + Get-VMHost -Name $VMHostName | Set-VMHost -State Maintenance -Confirm:$false -RunAsync + Disable-ITDVMwareVMHostFeature -Name $VMHostName -AlarmActions + } + catch { + Write-Error "Failed to set VMHost $VMHostName to Maintenance mode. Error: $_" + throw + } + } + 'Online' { + Write-Verbose "Setting VMHost $VMHostName to Online mode." + Get-VMHost -Name $VMHostName | Set-VMHost -State Connected -Confirm:$false -RunAsync + Enable-ITDVMwareVMHostFeature -Name $VMHostName -AlarmActions + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/README.md b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/Networks/rb-VMware-SyncVMwareSharePointNetwork-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/Networks/rb-VMware-SyncVMwareSharePointNetwork-prd.ps1 new file mode 100644 index 0000000..c4a08ba --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/Networks/rb-VMware-SyncVMwareSharePointNetwork-prd.ps1 @@ -0,0 +1,251 @@ +function Get-ITDVMwareSharePointNetworkList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000' + '&$select=ID,Title,Vlan_Id,CIDR,PA_Zone,Secure,AutoUpdate' + $InvokeWebRequestParams += @{ + Uri = $URL + Method = "Get" + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true + } + + $List = (Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + #$List = (Invoke-RestMethod -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +function Get-ITDPAInterface { + [CmdletBinding()] + Param ( + [string[]] + $Number + ) + + begin { + #[xml]$RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py').Content + $RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py') + $Zones = $RawXmlZones.response.result.zone.entry + $UniversalDenyZones = Get-ITDPAUniversalDenyZone + } + + process { + $result = @() + ForEach ($Zone in $Zones) { + #$Interfaces = $Zone.network.layer3.member | ForEach-Object{$_ -replace 'ae1.'} + $Interfaces = $Zone.network.layer3.member | ForEach-Object { $_ -replace "ethernet\d/\d\d." } + If ($Number) { + $Interfaces = (Compare-Object -ReferenceObject $Interfaces -DifferenceObject $Number -ExcludeDifferent -IncludeEqual).InputObject + } + ForEach ($Interface in $Interfaces) { + $obj = [PSCustomObject]@{ + Interface = $Interface; + Zone = $Zone.name + ZeroTrust = If (@($UniversalDenyZones) -eq $Zone.Name) { $true }Else { $false }; + } + $result += $obj + } + } + } + + end { + Write-Output $result + } +} + +function Get-ITDPAUniversalDenyZone { + [CmdletBinding()] + Param + ( + + ) + + Begin { + $Inbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Inbound') -split '[\r\n]+') | Where-Object { $_ -match "" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "") -replace "") -Replace " " | Sort-Object + $Outbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Outbound') -split '[\r\n]+') | Where-Object { $_ -match "" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "") -replace "") -Replace " " | Sort-Object + } + Process { + $result = Compare-Object -ReferenceObject $Inbound -DifferenceObject $Outbound -IncludeEqual | Sort-Object InputObject + } + End { + Write-Output ($result | Where-Object SideIndicator -EQ '==').InputObject + } +} + +function Set-ITDVMwareSharePointNetworkRecord { + [CmdletBinding()] + Param + ( + [string] + $Vlan_Id, + + [string] + $PA_Zone, + + [ValidateSet("True", "False")] + [string] + $Secure, + + [PSCredential] + $Credential + ) + + Begin { + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$ListItems=((Invoke-RestMethod -Uri $UrlListItem -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + $ListItems = ((Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + } + Process { + $RecordToModify = $ListItems | Where-Object Vlan_id -EQ $Vlan_Id + If (@($RecordToModify).count -gt 1) { + Write-Warning "More than one result, skipping $Vlan_Id" + } + Else { + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items($IDtoModify)" + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName } + } + + If ($PA_Zone) { $SetRecord += @{PA_Zone = $PA_Zone } } + If ($Secure) { $SetRecord += @{Secure = $Secure } } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + } + + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + Invoke-RestMethod @InvokeWebRequestParams + } + } + End { + + } +} + +$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' +$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + +$SharePointList = Get-ITDVMwareSharePointNetworkList -Credential $SharePointCredential + +$PAInterfaces = Get-ITDPAInterface -ErrorAction SilentlyContinue # | select *, @{n = 'Vlan_Id'; e = { $_.Interface.PadLeft(4, '0') } } + +If ($null -eq $PAInterfaces) { + +} +Else { + ForEach ($SPItem in $SharePointList) { + Write-Warning ($SPItem.Vlan_Id + ", " + $SPItem.CIDR + " - Start") + $change = $false + + If ($SPItem.AutoUpdate -eq $true) { + $SetITDVMwareSharePointVMNetworkParams = $null + + $PAItem = $PAInterfaces | Where-Object Interface -EQ ($SPItem.Vlan_Id -as [int]) + $SetITDVMwareSharePointVMNetworkParams = @{Vlan_Id = $SPItem.Vlan_Id; + Credential = $SharePointCredential + } + If ($PAItem.ZeroTrust) { + If ($SPItem.Secure -ne $PAItem.ZeroTrust) { + $SetITDVMwareSharePointVMNetworkParams += @{Secure = [bool]$PAItem.ZeroTrust } + $change = $true + } + } + Else { + If ($SPItem.Secure -eq $false) { + # Secure is accurate + } + Else { + $SetITDVMwareSharePointVMNetworkParams += @{Secure = $false } + $change = $true + } + } + + If ($SPItem.PA_Zone -ne $PAItem.Zone) { + $SetITDVMwareSharePointVMNetworkParams += @{PA_Zone = $PAItem.Zone } + $change = $true + } + + If ($Change -eq $true) { + Write-Warning ("Set VM network metadata: Vlan " + $SPItem.Vlan_Id + ", " + $SPItem.CIDR) + Set-ITDVMwareSharePointNetworkRecord @SetITDVMwareSharePointVMNetworkParams + } + + } + } +} + +$postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 5; + Platform = 'PowerShell-VMware-NetworkSync'; +} + +Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/Azure-ServicePrincipal.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/Azure-ServicePrincipal.ps1 new file mode 100644 index 0000000..259dde2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/Azure-ServicePrincipal.ps1 @@ -0,0 +1,10 @@ +$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' +$AppId = '60244573-7130-4026-9c6d-47de73f8ca29' +$SecureStringPwd = "sQV8Q~sNLcrDl2RgB32gsSEsDVgdFhNMcBdPoaEX" +#$zm = Get-Credential -username $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) + +$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force) +Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId + +# laptop +Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-Azure-NewAzureVMWindows-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-Azure-NewAzureVMWindows-prd.ps1 new file mode 100644 index 0000000..9fb0812 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-Azure-NewAzureVMWindows-prd.ps1 @@ -0,0 +1,843 @@ +# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d +<# +$ComputerName = 'itddotfrsql3.nd.gov' +$CPU = 8 +$MemoryGB = 32 +$OS = 'Windows Server 2019 Datacenter' +$Subnet = '10.21.12.0/22' +$Environment = "Production" +$Platform = "Azure" +$AppName = 'DOT-FacialRec' +$LicensingRestrictions='Microsoft SQL Enterprise' +$Credential = $PrvCred +#> +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +<# New-ITDVMwareWindowsVMAA +#> + +function New-ITDAzureWindowsVMAA { + [CmdLetBinding()] + Param( + [Parameter(Mandatory = $true)] + [string] + $ComputerName, + + [Parameter(Mandatory = $true)] + [int] + $CPU, + + [Parameter(Mandatory = $true)] + [int] + $MemoryGB, + + #[Parameter(Mandatory = $true)] + #[int] + #$DiskOS, + + #[Parameter(Mandatory = $true)] + #[int] + #$DiskData, + + [Parameter(Mandatory = $true)] + [string] + $Subnet, + + [Parameter(Mandatory = $true)] + [string] + $OS, + + [Parameter(Mandatory = $true)] + [string] + $Environment, + + [Parameter(Mandatory = $true)] + [string] + $AppName, + + [Parameter(Mandatory = $true)] + [string] + $LicensingRestrictions + + #[Parameter(Mandatory = $true)] + #[PSCredential] + #$Credential + ) + + + $Body = " + ComputerName=$ComputerName + CPU=$CPU + MemoryGB=$MemoryGB + VlanId=$VlanId + OS=$OS + Environment=$Environment + Datacenter=$Datacenter + LicensingRestrictions=$LicensingRestrictions + AppName=$AppName + + RunningOn=$env:computername + RunningAs=$env:username + Credential=$Credential.UserName + " + Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject "AutoBuildAzure-$ComputerName" + + $FQDN = $ComputerName + $tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' + + If ($Credential) { + $IaasAuto = $Credential + } + + #$IaasAutoAzApp = Get-AutomationPSCredential -Name 'Azure IaaS Service Principal' + + Write-Warning "[$FQDN]:Start" + $SPCred = $IaasAuto + $ADCred = $IaasAuto + $PSCred = $IaasAuto + $VMCred = $IaasAuto + $CcmCred = $IaasAuto + + #$RadiusCred = $RadiusCred + $RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password)) + + Clear-DnsClientCache + $HostName = $FQDN.split('.')[0] + + + + # Infoblox + #$InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred # not valid for Azure + #$Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() + $Cidr = $Subnet + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + + # Passwordstate + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred + #$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredential = $GuestCredentialBB + + switch ($Environment) { + { $_ -eq 'Test' -or $_ -eq 'Development' } { + Write-Warning 'Environment is Test or Development' + $EnvShortString = 'tst' + #$VMSizeFilter="*_B*s*" + $VMSizeFilter1 = "*_D[0-9]*s_v3" + $VMSizeFilter2 = "*_E[0-9]*s_v3" + $VMSizeFilter3 = "*_F[0-9]*s_v2" + + $Subscription = "npd01" + $VNet = "vnet-npd01-001" + $VNetSubnet = "sn-shared-zerotrust-npd-10.21.8.0_22" + } + 'Production' { + Write-Warning 'Environment is Production' + $EnvShortString = 'prd' + #$VMSizeFilter="*_D*s_*" + $VMSizeFilter1 = "*_D[0-9]*s_v3" + $VMSizeFilter2 = "*_E[0-9]*s_v3" + $VMSizeFilter3 = "*_F[0-9]*s_v2" + $Subscription = "prd01" + $VNet = "vnet-prd01-001" + $VnetSubnet = "sn-shared-zerotrust-prd-10.21.12.0_22" + } + 'CARES-tst' { + Write-Warning 'Environment is CARES-tst' + $EnvShortString = 'tst' + #$VMSizeFilter="*_D*s_*" + $VMSizeFilter1 = "*_D[0-9]*s_v3" + $VMSizeFilter2 = "*_E[0-9]*s_v3" + $VMSizeFilter3 = "*_F[0-9]*s_v2" + $Subscription = "cares01" + $VNet = "vnet-infra-azurenetworking-cares01-npd" + $VnetSubnet = "sn-shared-zerotrust-npd-10.69.254.0_24" + } + 'CARES-prd' { + Write-Warning 'Environment is CARES-prd' + $EnvShortString = 'prd' + #$VMSizeFilter="*_D*s_*" + $VMSizeFilter1 = "*_D[0-9]*s_v3" + $VMSizeFilter2 = "*_E[0-9]*s_v3" + $VMSizeFilter3 = "*_F[0-9]*s_v2" + $Subscription = "cares01" + $VNet = "vnet-infra-azurenetworking-cares01-prd" + $VnetSubnet = "sn-shared-zerotrust-prd-10.69.126.0_24" + } + + Default { + Write-Error "Environment failed" -ErrorAction Stop + } + } + + switch ($OS) { + "Windows Server 2019 Datacenter" { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2019-Datacenter" + } + "Windows Server 2022 Datacenter" { + $VMOS = "Windows" + $Publisher = "MicrosoftWindowsServer" + $Offer = "WindowsServer" + $sku = "2022-datacenter" + } + Default { Write-Error "Invalid operating system" -ErrorAction Stop } + } + + # finalize VM size + Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId + + $location = "centralus" + $VMSize = Get-AzVMSize -Location $location | ` + Where-Object { $_.Name -Like "$VMSizeFilter1" -or $_.Name -Like "$VMSizeFilter2" -or $_.Name -Like "$VMSizeFilter3" } | ` + Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | ` + Where-Object Name -NotMatch "_Promo" | ` + Sort-Object NumberOfCores, MemoryInMB | ` + Select-Object -First 1 + + + # resource group things + $VMOwner = $AppName.split('-')[0].ToLower() + $VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " " + #$IPAddress = (Resolve-DnsName -Name $ComputerName -ErrorAction Stop).IpAddress + $ResourceGroup = "rg-$VMOwner-$VMFunction-$EnvShortString" + If ($ResourceGroupIndex) { $ResourceGroup = $ResourceGroup + "-$ResourceGroupIndex" } + $VMName = "vm-$HostName-$EnvShortString" + + + $NewITDAzureRMVMParams = @{ + VMFQDN = $ComputerName + VMSubscription = $Subscription + VMEnvironment = $EnvShortString + VMOwner = $VMOwner + VMFunction = $VMFunction + VMSize = $VMSize.Name + VMOS = $VMOS + VMPublisher = $Publisher + VMOffer = $Offer + VMSku = $sku + VMVnetName = $VNet + VMSubnet = $VNetSubnet + VMLocation = $location + VMIP = $IPAddress.IPAddressToString + VMCredential = $LocalCredential + AppName = $AppName + } + <# + $VMFQDN = $ComputerName + $VMSubscription = $Subscription + $VMEnvironment = $EnvShortString + $VMOwner = $VMOwner + $VMFunction = $VMFunction + $VMSize = $VMSize.Name + $VMOS = $VMOS + $VMPublisher = $Publisher + $VMOffer = $Offer + $VMSku = $sku + $VMVnetName = $VNet + $VMSubnet = $VNetSubnet + $VMLocation = $location + $VMIP = $IPAddress + $VMCredential = $LocalCredential + $AppName = $AppName +#> + New-ITDAzureRMVM @NewITDAzureRMVMParams + + # wait for build + $VMName = ('vm-' + $ComputerName.split('.')[0] + '-' + $EnvShortString) + + $VMStatus = $null + $VMCreation = $Null + While ($VMCreation -ne "Complete") { + If (( (Get-AzVM -ResourceGroupName $ResourceGroup -Name $VMName -Status).Statuses | Where-Object Code -Match "PowerState").Code -eq "PowerState/running") { + $VMCreation = "Complete" + } + else { + Start-Sleep -Seconds 300 + } + } + + Start-Sleep -Seconds 30 + + # Add extra disk + Add-ITDAzureRMNewDataDisk -VMName $VMName -SizeGB 20 + + # pre-firewall Guest OS customization + Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\1-SetWMITags.ps1' + Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\3-Disks.ps1' + Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\5-TimeZone.ps1' + Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\6-PerformanceCounters.ps1' + Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\7-DisableWindowsFirewall.ps1' + + # determine Active Directory Forest and OU + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? + + +} + +function New-ITDAzureRMVM { + [CmdletBinding()] + Param + ( + # VM Computer Name (FQDN) + [Parameter(Mandatory = $true, Position = 0)] + [String] + $VMFQDN, + + # VM Subscription (tst,prd,dr) + [Parameter(Mandatory = $true)] + [string] + $VMSubscription, + + # Environment (tst,prd,dr) + [Parameter(Mandatory = $true)] + [string] + $VMEnvironment, + + # Owner (infra,shared,ITD,DHS,etc) + [Parameter(Mandatory = $true)] + [string] + $VMOwner, + + # Function (testdc, POC, etc) + [Parameter(Mandatory = $true)] + [string] + $VMFunction, + + #[Parameter(Mandatory=$true)] + [string] + $ResourceGroupIndexNumber, + + # Azure VM Size + [Parameter(Mandatory = $true)] + [string] + $VMSize, + + # Azure OS (Windows or Linux) + [Parameter(Mandatory = $true)] + [string] + $VMOS, + + # Availability Set + [switch] + $VMAS, + + # Availability Set Tier + [string] + $VMASTier, + + # Availability Zone + [ValidateSet(1, 2, 3)] + [int] + $VMAvailZone, + + # Azure Publisher + [string] + $VMPublisher, + + # Azure Offer + [string] + $VMOffer, + + # Azure Sku + [string] + $VMSku, + + # Azure vNet + [Parameter(Mandatory = $true)] + [string] + $VMVNetName, + + # Azure Subnet + [Parameter(Mandatory = $true)] + [string] + $VMSubnet, + + # Azure Location + [Parameter(Mandatory = $true)] + [string] + $VMLocation, + + # Azure Private IP + [Parameter(Mandatory = $true)] + [string] + $VMIP, + + [Parameter(Mandatory = $true)] + [PSCredential] + $VMCredential, + + # App name to be used for the RG + [Parameter(Mandatory = $true)] + [string] + $AppName + ) + Begin { + $VMName = $VMFQDN.Split('.')[0] + #$VMIndexNumber = "001" + $VMIPConfigName = "ipconfig-$VMName-$VMEnvironment" + $VMNicName = "nic-$VMName-$VMEnvironment" ###### + $VMObjectName = "vm-$VMName-$VMEnvironment" + $ResourceGroup = "rg-$VMOwner-$VMFunction-$VMEnvironment" + #If($ResourceGroupIndexNumber){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndexNumber"} + #removing diag storage account because replaced by managed storage accounts for boot diagnostics + #$VMDiagStorageAcct = "sa" + $VMOwner + $VMFunction + "diag" + $VMEnvironment + $VMOSDiskName = "vm-$VMName-os-$VMEnvironment" + + <# + If($VMASTier) + { + $VMASName = "as-$VMOwner-$VMFunction-$VMASTier-$VMEnvironment" + } + Else + { + $VMASName = "as-$VMOwner-$VMFunction-$VMEnvironment" + } + #> + + <# + Write-Verbose "Checking Storage Account Length" + If (($VmDiagStorageAcct.Length) -gt 24){ + Write-Verbose "Storage Account Length is too long. Truncating function...." + $TruncateCharacters = $VmDiagStorageAcct.Length - 24 + $ShortVMFunction = $VMFunction.Substring(0, ($VMFunction.length) - $TruncateCharacters) + $VMDiagStorageAcct = "sa" + $VMOwner + $ShortVMFunction + "diag" + $VMEnvironment + } + + If (($VmDiagStorageAcct.Length) -gt 24){ + Write-Verbose "Storage Account Length is too long after truncating. Terminating Build" + Return + } + #> + Write-Verbose "Verifying Applicable Inputs are Lowercase" + $VMIPConfigName = $VMIPConfigName.ToLower() + $VMNicName = $VMNicName.ToLower() + $VMObjectName = $VMObjectName.ToLower() + $ResourceGroup = $ResourceGroup.ToLower() + #$VMDiagStorageAcct = $VMDiagStorageAcct.ToLower() + $VMOSDiskName = $VMOSDiskName.ToLower() + } + Process { + Set-AzContext $VMSubscription + $ResGroupExist = "" + Write-Verbose "Creating Resource Group if it doesn't exist" + $ResGroupExist = Get-AzResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue + + + If (@($ResGroupExist).count -gt 1) { + Write-Error "Multiple Resource Groups matched" -ErrorAction Stop + } + If (@($ResGroupExist).count -lt 1) { + Write-Warning "No matching resource group found, creating it now" + New-AzResourceGroup -Name $ResourceGroup -Location $VMLocation -Tag @{ApplicationName = $AppName } + $ResourceGroupName = $ResourceGroupSearch.ResourceGroupName + #Write-Error "No Resource Groups matched" -ErrorAction Stop + } + If (@($ResGroupExist).count -eq 1) { + Write-Warning "Exactly one matching resource group found" + $ResourceGroupName = $ResourceGroupSearch.ResourceGroupName + } + + <# + Write-Verbose "Checking Storage Account Availability in Subscription" + If (!(Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $VMDiagStorageAcct})) + { + If ((Get-AzureRmStorageAccountNameAvailability -Name $VMDiagStorageAcct).NameAvailable -eq $True) + { + + New-AzureRmStorageAccount -Name $VMDiagStorageAcct -Location $VMLocation -ResourceGroupName $ResourceGroup -SkuName "Standard_LRS" -EnableHttpsTrafficOnly $true + #Start-Sleep -Seconds 5 + Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct | Update-AzureRmStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None + #Update-AzureRmStorageAccountNetworkRuleSet -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct -DefaultAction Deny -Bypass None + Add-AzureRmStorageAccountNetworkRule -ResourceGroupName $ResourceGroup -AccountName $VMDiagStorageAcct -IPAddressOrRange "165.234.248.3" + } + Else + { + Write-Verbose "Storage Account already exists. Re-run with a valid storage account" + Return + } + } + #> + <# + Write-Verbose "Evaluating Availability Set" + If($VMAS) + { + Write-Verbose "Checking for existing Availability Set" + $VMASExist = Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -ErrorAction SilentlyContinue + If($VMASExisting) + { + $VMASID = $VMASExist.id + } + Else + { + New-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -Location $VMLocation -PlatformFaultDomainCount 3 -PlatformUpdateDomainCount 5 -Sku Aligned + $VMASID = (Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName).id + } + } +#> + + Write-Verbose "Preparing Network Config" + $VNet = (Get-AzVirtualNetwork | where { $_.Name -eq $VMVNetName }) + $VNetID = $VNet.id + $Subnet = ($VNet.Subnets | where { $_.Name -eq $VMSubnet }) + $SubnetName = $Subnet.name + $SubnetID = $Subnet.id + + Write-Verbose "Creating IPConfig and NIC" + $IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $VMIP -PrivateIpAddressVersion IPv4 -Subnet $Subnet + $VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $VMLocation -Name $VMNICName -ResourceGroupName $ResourceGroup -SubnetId $SubnetID + $VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static" + $VMNIC.IpConfigurations[0].PrivateIpAddress = $VMIP + Set-AzNetworkInterface -NetworkInterface $VMNIC + + Write-Verbose "Building VM Config" + #If($VMAS) + #{ + #$vmConfig = New-AzVMConfig -VMName $VMObjectName -VMSize $VMSize -AvailabilitySetId $VMASID + #} + #Else + #{ + #If($VMAvailZone) + #{ + # Write-Verbose "AvailZone $VMAvailZone" + # $vmConfigParams = @{ + # VMName = $VMObjectName + # VMSize = $VMSize + # Zone = $VMAvailZone + # } + #} + #Else + #{ + # Write-Verbose "No AvailZone" + $vmConfigParams = @{ + VMName = $VMObjectName + VMSize = $VMSize + } + #} + #$vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize + $vmConfig = New-AzVMConfig @vmConfigParams + #} + + + + $vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage + If ($VMOS -eq "Windows") { + $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential + $vmConfig | Set-AzVMSourceImage -PublisherName $VMPublisher -Offer $VMOffer -Skus $VMSku -Version latest + } + If ($VMOS -eq "Linux") { + $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $VMCredential + Switch ($VMSubscription) { + #"npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} + #"infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} + #"prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-002"} + + "npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" } + "infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" } + "prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" } + } + } + + $vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID + #$vmConfig | Set-AzureRmVMBootDiagnostics -Enable -ResourceGroupName $ResourceGroup -StorageAccountName $VMDiagStorageAcct + ##set to use managed storage account after module conversion to Az + #$vmConfig | Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup + Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup + + Write-Verbose "Creating VM" + New-AzVM -VM $vmConfig -ResourceGroupName $resourceGroup -Location $VMLocation -DisableBginfoExtension -LicenseType "Windows_Server" -AsJob + + } + End { + } +} + +function Add-ITDAzureRMNewDataDisk { + [CmdletBinding()] + Param + ( + [string] + $VMName, + + [int[]] + $SizeGB + ) + + Begin { + $search = @() + $Hostname = $VMName.split('-')[1] + $Environment = $VMName.split('-')[2] + + Get-AzSubscription | ForEach-Object { + $Subscription = $_ + Set-AzContext $_ | Out-Null + $search += Get-AzVM | Where-Object Name -EQ $VMName | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } } + } + } + Process { + If ($search.count -eq 1) { + Set-AzContext $search.SubscriptionName + $ResourceGroup = $search.ResourceGroupName.ToLower() + $Location = (Get-AzResourceGroup -Name $ResourceGroup).Location + $VM = Get-AzVM -Name $VMName -ResourceGroupName $ResourceGroup + $Zone = $VM.Zones + + + ForEach ($Size in $SizeGB) { + $ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$environment-") } }) + + $NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1 + $NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000") + $NewDiskName = "vm-$Hostname-app-$Environment-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001 + + $LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1 + + $count = 0 + If ($ExistingDisks) { + while ($Size -match $ExistingDisks.DiskSizeGB) { + $count++ + Write-Warning "SizeGB: $Size, Count: $count" + If ($count -ge 11) { + Write-Error "Disk size not available" -ErrorAction Stop + } + Else { + $Size = $Size - 1 + } + } + } + + Write-Warning "SizeGB: $Size, Count: $count" + + $AzureRmDiskConfigParams = @{ + DiskSizeGB = $Size + Location = $Location + CreateOption = "Empty" + SkuName = "Premium_LRS" + } + + If ($Zone) { + Write-Verbose "VM is located in Zone $Zone" + $AzureRmDiskConfigParams += @{Zone = $Zone } + } + #$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS + $DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams + + If (!(Get-AzDisk -ResourceGroupName $ResourceGroup -DiskName $NewDiskName -ErrorAction SilentlyContinue)) { + $NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroup + + $VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroup -AsJob + } + } + } + Else { + Write-Error "Search count invalid" -ErrorAction SilentlyContinue + } + } + End { + } +} + +$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation' + +$IaasAutoCred = $IaaSAutoAz +<# +New-ITDAzureWindowsVMAA ` + -ComputerName itdbuilddba.nd.gov ` + -CPU 2 ` + -MemoryGB 8 ` + -Subnet '10.21.8.0/22'` + -OS 'Windows Server 2019 Datacenter' ` + -Environment 'Test' ` + -AppName 'Infra-SoftDev-TFS' ` + -LicensingRestrictions 'No Licensing Restrictions' ` + -verbose +#> + +<# + +$params = @{ + ComputerName = "itdpurshir1.nd.gov" + CPU = 2; + MemoryGB = 8; + Subnet = '10.69.254.0/24'; + OS = 'Windows Server 2022 Datacenter'; + Environment = 'CARES-tst'; + AppName = 'ITD-POC-Purview'; + LicensingRestrictions = 'No Licensing Restrictions'; + Verbose = $true; +} + +New-ITDAzureWindowsVMAA @params +#> +$params = @{ + ComputerName = "itdsoscmtsql22.nd.gov" + CPU = 4; + MemoryGB = 16; + Subnet = '10.21.8.0/22'; + OS = 'Windows Server 2022 Datacenter'; + Environment = 'Test'; + AppName = 'SOS-BLS'; + LicensingRestrictions = 'Microsoft SQL Standard'; + Verbose = $true; +} + +New-ITDAzureWindowsVMAA @params + + + +#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd-InvokeTest.ps1old b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd-InvokeTest.ps1old new file mode 100644 index 0000000..2fb5ced --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd-InvokeTest.ps1old @@ -0,0 +1,18 @@ +$RestMethodParams = @{ + Method = 'Post'; + Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d'; + Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV'}; + Body = [PSCustomObject]@{ + ComputerName = 'itddhsharvestp1.nd.gov'; + CPU = 2; + MemoryGB = 24; + VlanId = 3822; + OS = 'Windows Server 2022 Datacenter'; + Environment = 'Production'; + Datacenter = 'Bismarck'; + AppName = 'DHS-Orchard-Harvest'; + LicensingRestrictions = 'No Licensing Restrictions'; + } | ConvertTo-Json; +} + +Invoke-RestMethod @RestMethodParams | ConvertTo-Json \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1 new file mode 100644 index 0000000..83a7a14 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1 @@ -0,0 +1,1102 @@ +# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +function New-ITDVMwareWindowsVMAA { + [CmdLetBinding()] + Param( + [Parameter(Mandatory = $true)] + [string] + $ComputerName, + + [Parameter(Mandatory = $true)] + [int] + $CPU, + + [Parameter(Mandatory = $true)] + [int] + $MemoryGB, + + [Parameter(Mandatory = $true)] + [string] + $VlanId, + + [Parameter(Mandatory = $true)] + [string] + $OS, + + [Parameter(Mandatory = $true)] + [string] + $Environment, + + [Parameter(Mandatory = $true)] + [string] + $Datacenter, + + [Parameter(Mandatory = $true)] + [string] + $AppName, + + [Parameter(Mandatory = $true)] + [string] + $LicensingRestrictions, + + [Parameter(Mandatory = $true)] + [PSCredential] + $Credential + ) + #$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto + #$StdCred = $IaasAuto + #$PrvCred = $IaasAuto + + $Body = " + ComputerName=$ComputerName + CPU=$CPU + MemoryGB=$MemoryGB + VlanId=$VlanId + OS=$OS + Environment=$Environment + Datacenter=$Datacenter + LicensingRestrictions=$LicensingRestrictions + AppName=$AppName + + RunningOn=$env:computername + RunningAs=$env:username + Credential=$Credential.UserName + " + Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject "AutoBuildVMware-$ComputerName" + + $FQDN = $ComputerName + [string]$VLAN = $VlanId + + If ($Credential) { + $IaasAuto = $Credential + } + + Write-Warning "[$FQDN]:Start" + $SPCred = $IaasAuto + $ADCred = $IaasAuto + $PSCred = $IaasAuto + $VMCred = $IaasAuto + $CcmCred = $IaasAuto + + #$RadiusCred = $RadiusCred + $RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password)) + + Clear-DnsClientCache + $HostName = $FQDN.split('.')[0] + + # Infoblox + $InfobloxVlanMetadata = Get-ITDIbVlan -Vlan $VLAN -Credential $RadiusCred + $CIDR = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $CIDR.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + <# + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose "IP Address and CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop + } + #> + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + # Passwordstate BB before baseline, AB after baseline + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + + # Passwordstate validation WIP + <#$ExistingPassword = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $PSCred -ErrorAction SilentlyContinue +If($ExistingPassword){ + $LocalCredential = $ExistingPassword +}#> + + + + $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred + #$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredential = $GuestCredentialBB + + # VMware + If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Exit + } + + switch ($LicensingRestrictions) { + "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Enterprise" { $ClusterRoot = "SQL" } + "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "WINDOWS" } + "IBM Websphere" { $ClusterRoot = "WAS" } + "Powerschool" { $ClusterRoot = "PS" } + "Pexip" { $ClusterRoot = "TEL" } + } + + switch ($Datacenter) { + "Bismarck" { $ClusterInt = 1 } + "Mandan" { $ClusterInt = 2 } + } + + $Cluster = $ClusterRoot + $ClusterInt + + switch ($Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + $DiskStorageFormat = 'EagerZeroThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + $DiskStorageFormat = 'EagerZeroThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen" + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + } + + # verify disk will fit + $DiskTotal = 70 + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + switch ($OS) { + "Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Datacenter 1809.18" } + "Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Datacenter 2108.13" } + Default { Write-Error "Invalid template" -ErrorAction Stop } + } + + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $VLAN + "*") + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + Write-Warning ("ViServer = $ViServer") + + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + + Get-OSCustomizationSpec -Name 'Windows (Auto)' -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + <# + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + $NewVMParams + + New-VM @NewVMParams + #> + + Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294 + # seems fixed on 2022/07/01 -- is not fixed 2022/10/28 + try { + Write-Warning $FQDN + Write-Warning $ComputeCluster.Name + Write-Warning $DatastoreCluster + Write-Warning $DiskStorageFormat + Write-Warning $Template + Write-Warning $FolderLocation + Write-Warning $OSSpec + New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec + } + catch { + Write-Error $error[0] + Exit + } + + #If (!($BuildError)) { + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + # Delete OS Customization Spec + # Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + + # Add/Expand Disks + Write-Warning -Message "[$FQDN]:Modify disks 1,2,3" + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt 60) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB 60 -Confirm:$false + } + + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB ($MemoryGB + 1) ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt ($MemoryGB + 1)) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB ($MemoryGB + 1) -Confirm:$false + } + + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB 20 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt 20) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB 20 -Confirm:$false + } + + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category AppName -Name $AppName) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category DTAP -Name $Environment) -Server $VIServer + + # skipping tag assignment for now + # Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose + + # Run Guest OS code + # Enable RDP with NLA - can be done with GPO + # Enable WinRM - ITD WinRM enable + # Configure Power Plan - ITD-PowerPlan-HighPerformance + # Activate Windows, KMS on-premise, Azure to Azure + # DVD Drive to Z: + # Expand C: + # Partition/Format the rest, GPT/NTFS + # Configure Page File Disk + # Enabling server manager performance monitors + # Configure Time Zone and NTP - no GPO available + # Disable Windows Firewall + # Join AD + + #Initialize-ITDServer -Credential $ADCred + + + Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {get-childitem} + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + + Write-Warning -Message "[$FQDN]:Checking for DVD drive..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Expand C: Partition To Maximum Extent + + + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning "[$FQDN]:Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + + Write-Warning "[$FQDN]:Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Warning -Message "[$FQDN]:Enabling Remote Management..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking current power plan..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + <# + Write-Verbose -Message "Beginning a time synchronization..." + + if ((Get-Service W32Time).Status -eq 'Stopped') { + Start-Service W32Time + } + + [void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update) + + [void](& w32tm.exe /resync /nowait) + + # Start background job to check time service + $tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock { + do { + $tmOut = & w32tm.exe /query /status /verbose + + Start-Sleep -Seconds 10 + } until($tmOut -match '^Last Sync Error: 0\D+$') + } + + # If after three minutes time still has not synched, move on. This usually causes no problems. + if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') { + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful." + } + else { + [void](Stop-Job -Job $tmJob) + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed." + } + #> + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + + # Active Directory + Write-Warning "[$FQDN]:Join Active Directory (if required)" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + else { + $GuestCredentialAB = $GuestCredentialBB + } + + Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) + Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date)) + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Warning "[$FQDN]:Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Warning -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + # vcenter tags + #AppName Tag + + + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + #Start-Sleep -Seconds 180 + + Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...' + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + } + #> + + + Write-Warning "[$FQDN]:End" + <# +Invoke-Command -ComputerName $FQDN -Credential $PrvCred -ScriptBlock { Get-Process -Name ccmexec*, cohesity*, cyserver*, nessus*, vmtoolsd* } | sort-object PSComputerName,ProcessName + +Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" +Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); +}#> +} + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') { + Write-Verbose "Header has required data" + Write-Host $ + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + +} + +$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation' + +Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore + +Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred + +New-ITDVMwareWindowsVMAA -ComputerName $InputParams.ComputerName ` + -CPU $InputParams.CPU ` + -MemoryGB $InputParams.MemoryGB ` + -VlanId $InputParams.VlanId ` + -OS $InputParams.OS ` + -Environment $InputParams.Environment ` + -Datacenter $InputParams.Datacenter ` + -AppName $InputParams.AppName ` + -LicensingRestrictions $InputParams.LicensingRestrictions ` + -Credential $IaasAutoCred + +$postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 90; + Platform = 'PowerShell-VMware-VMWindows'; +} + +Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue + +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1-old b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1-old new file mode 100644 index 0000000..6b18a64 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/prod/rb-VMware-NewVMwareVMWindows-prd.ps1-old @@ -0,0 +1,1101 @@ +# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + # ignore certs https://communities.vmware.com/t5/VMware-PowerCLI-Discussions/Error-running-Invoke-Vmscript-An-error-occurred-while-sending/m-p/475203 + Add-Type @" +using System.Net; + +using System.Security.Cryptography.X509Certificates; + +public class TrustAllCertsPolicy : ICertificatePolicy { + + public bool CheckValidationResult( + + ServicePoint srvPoint, X509Certificate certificate, + + WebRequest request, int certificateProblem) { + + return true; + + } + +} + +"@ + + [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $FQDN = $InputParams.Title + + $SPCred = $StdCred + $ADCred = $PrvCred + $PSCred = $PrvCred + $VMCred = $PrvCred + $CcmCred = $PrvCred + #> + <# Get Credentials + + $SPCred = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + $ADCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $PSCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $IBCred = New-Object System.Management.Automation.PSCredential ($PSCred.UserName.split('\')[1], $ADCred.Password) + $VMCred = Get-AutomationPSCredential -Name 'VMware Auto' + $CcmCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'#> + #> + Clear-DnsClientCache + $SharePointList = Get-ITDVMwareSharePointVMGuestList -Credential $SPCred + Write-Warning ("SPList count: " + $SharePointList.count) + $SPItem = $SharePointList | Where-Object Title -EQ $FQDN + If ($null -eq $SPItem.Cluster) { + Write-Error "VMware Cluster not specified in SharePoint" + Stop + } + Write-Warning $SPItem + $HostName = $FQDN.split('.')[0] + + # Infoblox + [Net.IpAddress]$NetworkId = $SPItem.CIDR.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $SPItem.Cidr.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $SPItem.Cidr.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($SPItem.Cidr.split('/')[0].split('.')[-1] -as [int]) + 1) ) + <# + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose "IP Address and CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop + } + #> + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $SPItem.Title -CIDR $SPItem.CIDR -Credential $RadiusCred + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + } + #> + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + + # Passwordstate BB before baseline, AB after baseline + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredential = $GuestCredentialBB + + # VMware + Connect-ITDvCenter -Credential $VMCred + If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Stop + Stop + } + + switch ($SPItem.Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($SPItem.LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($SPItem.LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + } + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen" + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-PS1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-PS2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + <# + "DCN1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-DCN-vMotion-Data" + $DiskStorageFormat = 'Thin' + } + #> + } + + # verify disk will fit + + $DiskTotal = $SPItem.Disk1 + $SPItem.Disk2 + $SPItem.Disk3 + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $SPItem.Cluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + switch ($SPItem.OS) { + "Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" } + Default {} + } + + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $SPItem.Vlan_Id + "*") + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + <# + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + $NewVMParams + + New-VM @NewVMParams + #> + + #Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294 + # seems fixed on 2022/07/01 + try { + Write-Warning $FQDN + Write-Warning $ComputeCluster.Name + Write-Warning $DatastoreCluster + Write-Warning $DiskStorageFormat + Write-Warning $Template + Write-Warning $FolderLocation + Write-Warning $OSSpec + New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec + } + catch { + Stop + Stop + } + + #If (!($BuildError)) { + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $SPItem.Processors -MemoryGB $SPItem.RAM -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + # Delete OS Customization Spec + # Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + + # Add/Expand Disks + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + If ($SPItem.Disk1) { + If (!$VMDisk1) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk1 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $SPItem.Disk1) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $SPItem.Disk1 -Confirm:$false + } + } + + If ($SPItem.Disk2) { + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk2 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $SPItem.Disk2) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $SPItem.Disk2 -Confirm:$false + } + } + + If ($SPItem.Disk3) { + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk3 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false + } + } + + # skipping tag assignment for now + # Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose + + # Run Guest OS code + # Enable RDP with NLA - can be done with GPO + # Enable WinRM - ITD WinRM enable + # Configure Power Plan - ITD-PowerPlan-HighPerformance + # Activate Windows, KMS on-premise, Azure to Azure + # DVD Drive to Z: + # Expand C: + # Partition/Format the rest, GPT/NTFS + # Configure Page File Disk + # Enabling server manager performance monitors + # Configure Time Zone and NTP - no GPO available + # Disable Windows Firewall + # Join AD + + #Initialize-ITDServer -Credential $ADCred + + + Write-Warning -Message "Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "Checking for DVD drive..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "Checking for unpartitioned space on C: disk..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Expand C: Partition To Maximum Extent + + + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning "Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + + Write-Warning "Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Warning -Message "Enabling Remote Management..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "Checking current power plan..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + <# + Write-Verbose -Message "Beginning a time synchronization..." + + if ((Get-Service W32Time).Status -eq 'Stopped') { + Start-Service W32Time + } + + [void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update) + + [void](& w32tm.exe /resync /nowait) + + # Start background job to check time service + $tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock { + do { + $tmOut = & w32tm.exe /query /status /verbose + + Start-Sleep -Seconds 10 + } until($tmOut -match '^Last Sync Error: 0\D+$') + } + + # If after three minutes time still has not synched, move on. This usually causes no problems. + if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') { + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful." + } + else { + [void](Stop-Job -Job $tmJob) + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed." + } + #> + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Warning -Message "Enabling the server manager performance monitors..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + + # Active Directory + Write-Warning "Join Active Directory (if required)" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + $AppName = $SPItem.AppName + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + + Write-Warning "Copying SCCM client installer to C:\temp..." + Copy-VMGuestFile -Source D:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Warning "Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Warning -Message "Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + Write-Warning "Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Warning "Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + #Start-Sleep -Seconds 180 + + Write-Warning -Message 'Waiting for network connectivity / Then KVM Activation...' + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + } + <# + Write-Warning "Trigger SCCM DiscoverData until it works" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + $discoveryran = $false + while ($discoveryran -eq $false) { + try { + Write-Warning -Message ("Attempt DiscoveryData run " + (Get-Date)) + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000003}"); + $discoveryran = $true + } + catch { + Start-Sleep -Seconds 30 + } + } + } + Start-Sleep -Seconds 180 + + Write-Warning "Trigger SCCM MachinePolicy after Discovery" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Warning "Trigger SCCM UpdateDeployment Policy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000108}"); #updatedeployment + } + Start-Sleep -Seconds 30 + + Write-Warning "Trigger SCCM UpdateScan Policy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000113}"); #updatescan + } + Start-Sleep -Seconds 300 + + Write-Warning "Wait for SCCM Baselines" + While ( (Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { Get-WmiObject -Namespace root/ccm/dcm -Class SMS_DesiredConfiguration | where-object { $_.DisplayName -like "ITD-WMITag-DTAP*" } | Select-Object DisplayName, LastEvalTime, Status, Version | Sort-Object DisplayName }) -eq $null) { + Write-Warning -Message ((Get-Date -uformat "%Y/%m/%d %H:%M:%S") + " $FQDN waiting for baselines") + } + Start-Sleep -Seconds 60 + + Write-Warning "Evaluate SCCM Baselines" + $CIBaselineDTAP = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + Get-WmiObject -Namespace root/ccm/dcm -Class SMS_DesiredConfiguration | where-object { $_.DisplayName -like "ITD-WMITag-DTAP*" } | Select-Object DisplayName, LastEvalTime, Status, Version | Sort-Object DisplayName + } + #If ($CIBaselineDTAP.ScriptOutput -match "00000000000000.000000+000") { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + $Baseline = Get-WmiObject -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration | Where-Object DisplayName -like "ITD-WMITag-DTAP*" + ([wmiclass]"\\localhost\root\ccm\dcm:SMS_DesiredConfiguration").TriggerEvaluation($Baseline.Name, $Baseline.Version) + } + Start-Sleep -Seconds 30 + + $CIBaselineNum = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + Get-WmiObject -Namespace root/ccm/dcm -Class SMS_DesiredConfiguration | where-object { $_.DisplayName -like "ITD-ServerBaseline-*" } | Select-Object DisplayName, LastEvalTime, Status, Version | Sort-Object DisplayName + } + #If ($CIBaselineNum.ScriptOutput -match "00000000000000.000000+000") { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + $Baseline = Get-WmiObject -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration | Where-Object DisplayName -like "ITD-ServerBaseline-*" + ([wmiclass]"\\localhost\root\ccm\dcm:SMS_DesiredConfiguration").TriggerEvaluation($Baseline.Name, $Baseline.Version) + } + Start-Sleep -Seconds 30 + + + Write-Warning "Evaluate All Remaining Configuration Items" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + $CIs = Get-WmiObject -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration | where-object LastEvalTime -eq "00000000000000.000000+000" + ForEach ($CI in $CIs) { + ([wmiclass]"\\localhost\root\ccm\dcm:SMS_DesiredConfiguration").TriggerEvaluation($CI.Name, $CI.Version) + } + } + + Write-Warning "Trigger SCCM AppDeployment Policy " + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000121}"); + } + Start-Sleep -Seconds 30 + + Write-Warning "Install Available Updates" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType Powershell -ScriptText { + ([wmiclass]'ROOT\ccm\ClientSDK:CCM_SoftwareUpdatesManager').InstallUpdates([System.Management.ManagementObject[]] (Get-WmiObject -query 'SELECT * FROM CCM_SoftwareUpdate' -namespace 'ROOT\ccm\ClientSDK')) + } + Start-Sleep -Seconds 600 + + Write-Warning "Run gpupdate /force" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredential -ScriptType PowerShell -ScriptText { Invoke-Expression -Command "gpupdate /force" } + + <# + Write-Warning -Message "Restart VMGuest, wait for Tools, then 90 seconds after" + $GuestCredential = $GuestCredentialAB + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + #> + + + ############################## KEEP TEMPLATE UPDATED INSTEAD + + ############ force baselines + + <##### + install applications here + #> + <##### verify updates are available + get-wmiobject -query "SELECT * FROM CCM_SoftwareUpdate" -namespace "ROOT\ccm\ClientSDK" + #> + + + <####### pending reboot +NameSpace=’ROOT\ccm\ClientSDK’ + Class=’CCM_ClientUtilities’ + Method Name=’DetermineIfRebootPending’ + #> +} + +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/test/rb-VMware-NewVMwareVMWindows-tst.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/test/rb-VMware-NewVMwareVMWindows-tst.ps1 new file mode 100644 index 0000000..a2601e3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuilds/test/rb-VMware-NewVMwareVMWindows-tst.ps1 @@ -0,0 +1,358 @@ +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq '6EE8DaFMbswirY38qPfewwT82G9Bdiv8p3SKEdisX88mfnFfiredy6uti4nJprecedegJkTGBHDV3alpineePkM5grainsE56xp3JmuffWjwL') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $FQDN = 'itdzmbuild01.nd.gov' + + # Get Credentials + $SPCred = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + $ADCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $PSCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $IBCred = New-Object System.Management.Automation.PSCredential ($ADCred.UserName.split('\')[1], $ADCred.Password) + $VMCred = Get-AutomationPSCredential -Name 'VMware Auto' + + Clear-DnsClientCache + $SharePointList = Get-ITDVMwareSharePointVMGuestListTst -Credential $SPCred + $SPItem = $SharePointList | Where-Object Title -eq $FQDN + $HostName = $FQDN.split('.')[0] + + # Infoblox + [Net.IpAddress]$NetworkId = $SPItem.CIDR.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $SPItem.Cidr.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $SPItem.Cidr.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($SPItem.Cidr.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose "IP Address and CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop + } + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -HostName $SPItem.Title -CIDR $SPItem.CIDR -Credential $IBCred + } + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + + # Active Directory + If ($PSEdition -eq 'Core') { Import-Module ActiveDirectory -UseWindowsPowerShell } + $Filter = ("{Name -eq '" + $SPItem.AppName + "'}") + $OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter $Filter + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Identity $Hostname -ErrorAction SilentlyContinue + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + } + Else { + Write-Error "AD object already exists, OU path mismatch" + Exit + Exit + } + } + else { + switch ($SPItem.Environment) { + 'Test' { + $OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Test*" + } + 'Production' { + $OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Prod*" + } + } + If ($OUAppNameEnv) { $OUFinal = $OUAppNameEnv } + Else { $OUFinal = $OUAppName } + + New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json) + } + + # Passwordstate + $LocalCredential = New-ITDPassword -Title $FQDN -Username itdadmin -Description 'Local Administrator' -PasswordList CSRC -Credential $PrvCred + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + + # VMware + If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Stop + Stop + } + + switch ($SPItem.Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data" + $DiskStorageFormat = 'Thin' + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data" + $DiskStorageFormat = 'Thin' + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data" + $DiskStorageFormat = 'EagerZeroedThick' + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data" + $DiskStorageFormat = 'EagerZeroedThick' + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data" + $DiskStorageFormat = 'Thin' + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data" + $DiskStorageFormat = 'Thin' + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-PS1-Data" + $DiskStorageFormat = 'Thin' + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-PS2-Data" + $DiskStorageFormat = 'Thin' + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + } + "DCN1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-DCN-vMotion-Data" + $DiskStorageFormat = 'Thin' + } + } + + # verify disk will fit + $DiskTotal = $SPItem.Disk1 + $SPItem.Disk2 + $SPItem.Disk3 + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -like ("*" + $SPItem.Cluster + "*") + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Verbose ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Verbose ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + + $FolderLocation = Get-Folder -Server $ViServer -Name "_New Builds" + + switch ($SPItem.OS) { + "Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" } + Default {} + } + + $PortGroupsAvailable = Get-VDPortGroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -eq ("dvPG_" + $SPItem.Vlan_Id + "_" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt) + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent + + Get-OSCustomizationSpec -Name $NewOSSpecName | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password ` + + Get-OSCustomizationSpec -Name $NewOSSpecName | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.2.5.40" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName + + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + + New-VM @NewVMParams + + #If (!($BuildError)) { + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $SPItem.Processors -MemoryGB $SPItem.RAM -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + # Delete OS Customization Spec + Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + + # Add/Expand Disks + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + If ($SPItem.Disk1) { + If (!$VMDisk1) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk1 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $SPItem.Disk1) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $SPItem.Disk1 -Confirm:$false + } + } + + If ($SPItem.Disk2) { + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk2 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $SPItem.Disk2) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $SPItem.Disk2 -Confirm:$false + } + } + + If ($SPItem.Disk3) { + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk3 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false + } + } + + # Run Guest OS code + + $InvokeVMScriptFunc = { + + } + + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptText $InvokeVMScriptFunc + #} +} + +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/AutoBuildInputFileExample.csv b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/AutoBuildInputFileExample.csv new file mode 100644 index 0000000..4e5d403 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/AutoBuildInputFileExample.csv @@ -0,0 +1,2 @@ +"target_platform","target_hostname","target_cpus","target_memory","target_osdisk","target_datadisk","target_subnet","target_os","target_environment","target_vm_app_name","target_datacenter","target_licensingrestrictions" +"VMware","itdzmtest110.nd.gov","1","4","50","20","10.11.12.0/23","Windows Server 2022 Datacenter","Production","ITD-POC-zmeier","Bismarck","No Licensing Restrictions" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVM b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVM new file mode 100644 index 0000000..e69de29 diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVMFromCsv.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVMFromCsv.ps1 new file mode 100644 index 0000000..a2762d2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/New-ITDVMwareWindowsVMFromCsv.ps1 @@ -0,0 +1,64 @@ +$DriveLetter = 'D' +$CsvPath = ($DriveLetter + ":\AutoBuildInputFiles\") +$FailedPath = ($DriveLetter + ":\AutoBuildInputFiles\Failed") +$CompletedPath = ($DriveLetter + ":\AutoBuildInputFiles\Completed") + +$GetBuildFile = Get-ChildItem -Path $CsvPath -Filter *.csv | Sort-Object LastWriteTime | select -First 1 + +#$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation' +$IaasAutoCred = $PrvCred + +Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore + +$InputParams = Import-Csv -Path $GetBuildFile.FullName + +$ComputerName = $InputParams.target_hostname.ToLower() +Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $InputParams -Subject ("AutoBuildFromFile-$ComputerName-" + $InputParams.target_platform) + +try { + switch ($InputParams.target_platform) { + 'azure' { + + } + 'vmware' { + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred + + New-ITDVMwareWindowsVM -ComputerName $ComputerName ` + -CPU $InputParams.target_cpus ` + -MemoryGB $InputParams.target_memory ` + -DiskOS $InputParams.target_osdisk ` + -DiskData $InputParams.target_datadisk ` + -Subnet $InputParams.target_subnet ` + -OS $InputParams.target_os ` + -Environment $InputParams.target_environment ` + -Datacenter $InputParams.target_datacenter ` + -AppName $InputParams.target_vm_app_name ` + -LicensingRestrictions $InputParams.target_licensingrestrictions ` + -Credential $IaasAutoCred ` + -Verbose + + Move-Item -Path $GetBuildFile.FullName -Destination $CompletedPath + + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 240; + Platform = 'PowerShell-VMware-VMWindows'; + } + + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) + + } + } +} +catch { + $error[0] + Write-Warning "Email vmware admins about failure" + $Body = $error[0] | Select-Object * + Send-MailMessage -From autobuild@nd.gov -To "zmeier@nd.gov" -Subject "Failure-AutoBuildFromFile-$ComputerName" -SmtpServer apprelay.nd.gov -Body $Body + + Write-Warning "Error detected. Moving csv input file to folder Failed" + Move-Item -Path $GetBuildFile.FullName -Destination $FailedPath +} + +Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd-Invoke.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd-Invoke.ps1 new file mode 100644 index 0000000..b291d0b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd-Invoke.ps1 @@ -0,0 +1,31 @@ +$RestMethodParams = @{ + Method = 'Post'; + Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d'; + Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV' }; + Body = [PSCustomObject]@{ + target_platform = "VMware" + target_hostname = 'itdcndsperms.nd.gov'; + target_cpus = 1; + target_memory = 8; + target_osdisk = 100; + target_datadisk = 20; # this is now swap + target_subnet = '10.221.8.0/28'; + target_os = 'Windows Server 2019 Datacenter'; + target_environment = 'Production'; + target_vm_app_name = 'Shared-PeopleSoft-State'; + target_datacenter = 'Bismarck'; + target_licensingrestrictions = 'No Licensing Restrictions'; + } | ConvertTo-Json; +} + +Invoke-RestMethod @RestMethodParams + +$VMNames=@" +itdcndhftdb22.nd.gov +itdcndhhtdb22.nd.gov +"@ +$VMNames = ConvertTo-Array -MultiLineString $VMNames + +Invoke-Command -ComputerName $VMNames -Credential $PrvCred -ScriptBlock { + Get-Process -Name ccmexec*,cohesity*,cortex*,nessus*,vmtoolsd* +} | sort-object PSComputerName \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd.ps1 new file mode 100644 index 0000000..3e6c26a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVMWindows-prd.ps1 @@ -0,0 +1,1131 @@ +#https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +function New-ITDVMwareWindowsVMAA { + [CmdLetBinding()] + Param( + [Parameter(Mandatory = $true)] + [string] + $ComputerName, + + [Parameter(Mandatory = $true)] + [int] + $CPU, + + [Parameter(Mandatory = $true)] + [int] + $MemoryGB, + + [Parameter(Mandatory = $true)] + [int] + $DiskOS, + + [Parameter(Mandatory = $true)] + [int] + $DiskSwap, + + [int] + $DiskData = 0, + + <#[Parameter(Mandatory = $true)] + [string] + $VlanId,#> + + [Parameter(Mandatory = $true)] + [string] + $Subnet, + + [Parameter(Mandatory = $true)] + [string] + $OS, + + [Parameter(Mandatory = $true)] + [string] + $Environment, + + [Parameter(Mandatory = $true)] + [string] + $Datacenter, + + [Parameter(Mandatory = $true)] + [string] + $AppName, + + [Parameter(Mandatory = $true)] + [string] + $LicensingRestrictions, + + [Parameter(Mandatory = $true)] + [PSCredential] + $Credential + ) + #$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto + #$StdCred = $IaasAuto + #$PrvCred = $IaasAuto + + $ComputerName = $ComputerName.ToLower() + $FQDN = $ComputerName + + If ($Credential) { + $IaasAuto = $Credential + } + + Write-Warning "[$FQDN]:Start" + $SPCred = $IaasAuto + $ADCred = $IaasAuto + $PSCred = $IaasAuto + $VMCred = $IaasAuto + $CcmCred = $IaasAuto + + If($Environment -eq "Development"){ + $Environment = "Test" + } + + #$RadiusCred = $RadiusCred + $RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password)) + + Clear-DnsClientCache + $HostName = $FQDN.split('.')[0] + + # Infoblox + $InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred + $Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() + [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $CIDR.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $Subnet.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + Start-Sleep -Seconds 5 + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + + + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + } + + # Passwordstate BB before baseline, AB after baseline + Write-Warning "Start Passwordstate" + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred + #$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredential = $GuestCredentialBB + + # VMware + Write-Warning "Verify VM doesn't exist" + If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Exit + } + + Write-Warning "Decide Licensing" + switch ($LicensingRestrictions) { + "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Enterprise" { $ClusterRoot = "SQL" } + "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "WINDOWS" } + "IBM Websphere" { $ClusterRoot = "WAS" } + "Powerschool" { $ClusterRoot = "PS" } + "Pexip" { $ClusterRoot = "TEL" } + } + + Write-Warning "Decide Datacenter" + switch ($Datacenter) { + "Bismarck" { $ClusterInt = 1 } + "Mandan" { $ClusterInt = 2 } + } + + $Cluster = $ClusterRoot + $ClusterInt + Write-Warning "$Cluster decided, getting details" + + switch ($Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + $DiskStorageFormat = 'EagerZeroedThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen" + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + } + + # verify disk swap is sized at or above minimum, if diskdata should be populated, and that it all will fit datastore + If($DiskSwap -lt ($MemoryGB + 1)){ + [int]$DiskSwap = $MemoryGB + 1 + } + + If($ComputerName -like "itdcnd*"){ + $DiskData = 0 + } + Else{ + $DiskData = 20 + } + + $DiskTotal = $DiskOS + $DiskSwap + $DiskData + + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + switch ($OS) { + "Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Datacenter 1809.18" } + "Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Datacenter 2108.13" } + Default { Write-Error "Invalid template" -ErrorAction Stop } + } + + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_*" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt) + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + Write-Warning ("ViServer = $ViServer") + + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + + Get-OSCustomizationSpec -Name 'Windows (Auto)' -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + <# + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + $NewVMParams + + New-VM @NewVMParams + #> + + Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294 + # seems fixed on 2022/07/01 -- is not fixed 2022/10/28 + try { + Write-Warning $FQDN + Write-Warning $ComputeCluster.Name + Write-Warning $DatastoreCluster + Write-Warning $DiskStorageFormat + Write-Warning $Template + Write-Warning $FolderLocation + Write-Warning $OSSpec + New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec + } + catch { + Write-Error $error[0] + Exit + } + + #If (!($BuildError)) { + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + # Delete OS Customization Spec + # Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + + # Add/Expand Disks + Write-Warning -Message "[$FQDN]:Modify disks 1,2,3" + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $DiskOS) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $DiskOS -Confirm:$false + } + + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB ($MemoryGB + 1) ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $DiskSwap) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $DiskSwap -Confirm:$false + } + + If ($DiskData -gt 0) { + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $DiskData ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $DiskData) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $DiskData -Confirm:$false + } + } + + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category AppName -Name $AppName) -Server $VIServer + New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category DTAP -Name $Environment) -Server $VIServer + + # skipping tag assignment for now + # Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose + + # Run Guest OS code + # Enable RDP with NLA - can be done with GPO + # Enable WinRM - ITD WinRM enable + # Configure Power Plan - ITD-PowerPlan-HighPerformance + # Activate Windows, KMS on-premise, Azure to Azure + # DVD Drive to Z: + # Expand C: + # Partition/Format the rest, GPT/NTFS + # Configure Page File Disk + # Enabling server manager performance monitors + # Configure Time Zone and NTP - no GPO available + # Disable Windows Firewall + # Join AD + + #Initialize-ITDServer -Credential $ADCred + + + Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking for DVD drive..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Expand C: Partition To Maximum Extent + + + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning "[$FQDN]:Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + + Write-Warning "[$FQDN]:Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Warning -Message "[$FQDN]:Enabling Remote Management..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking current power plan..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + <# + Write-Verbose -Message "Beginning a time synchronization..." + + if ((Get-Service W32Time).Status -eq 'Stopped') { + Start-Service W32Time + } + + [void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update) + + [void](& w32tm.exe /resync /nowait) + + # Start background job to check time service + $tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock { + do { + $tmOut = & w32tm.exe /query /status /verbose + + Start-Sleep -Seconds 10 + } until($tmOut -match '^Last Sync Error: 0\D+$') + } + + # If after three minutes time still has not synched, move on. This usually causes no problems. + if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') { + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful." + } + else { + [void](Stop-Job -Job $tmJob) + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed." + } + #> + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + + # Active Directory + Write-Warning "[$FQDN]:Join Active Directory (if required)" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + else { + $GuestCredentialAB = $GuestCredentialBB + } + + Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) + Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date)) + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Warning "[$FQDN]:Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Warning -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + # vcenter tags + #AppName Tag + + + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + #Start-Sleep -Seconds 180 + + Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...' + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + } + Write-Warning "[$FQDN]:End" +} + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') { + Write-Verbose "Header has required data" + Write-Host $ + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + + $IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore + + $Body = $InputParams + <# + $Body = " + ComputerName=$ComputerName + CPU=$CPU + MemoryGB=$MemoryGB + Subnet=$Subnet + OS=$OS + Environment=$Environment + Datacenter=$Datacenter + LicensingRestrictions=$LicensingRestrictions + AppName=$AppName + + RunningOn=$env:computername + RunningAs=$env:username + Credential=$Credential.UserName + "#> + $ComputerName = $InputParams.target_hostname.ToLower() + $TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + $InputParams | Export-Csv "E:\AutoBuildInputFiles\$ComputerName-$TimeStamp.csv" -NoTypeInformation + Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject ("AutoBuildAA-$ComputerName-" + $InputParams.target_platform) + + <#switch ($InputParams.target_platform) { + 'azure' { + + } + 'vmware' { + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred + + New-ITDVMwareWindowsVMAA -ComputerName $InputParams.target_hostname ` + -CPU $InputParams.target_cpus ` + -MemoryGB $InputParams.target_memory ` + -DiskOS $InputParams.target_osdisk ` + -DiskSwap $InputParams.target_datadisk ` + -Subnet $InputParams.target_subnet ` + -OS $InputParams.target_os ` + -Environment $InputParams.target_environment ` + -Datacenter $InputParams.target_datacenter ` + -AppName $InputParams.target_vm_app_name ` + -LicensingRestrictions $InputParams.target_licensingrestrictions ` + -Credential $IaasAutoCred + + Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue + } + }#> + + + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 180; + Platform = 'PowerShell-VMware-VMWindows'; + } + + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) + + +} +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVM_CreateFile-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVM_CreateFile-prd.ps1 new file mode 100644 index 0000000..9612e17 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMBuildsV2/rb-NewVM_CreateFile-prd.ps1 @@ -0,0 +1,23 @@ +#https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') { + Write-Verbose "Header has required data" + Write-Host $ + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $ComputerName = $InputParams.target_hostname.ToLower() + $TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + $InputParams | Export-Csv "E:\AutoBuildInputFiles\$ComputerName-$Timestamp.csv" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/old/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/old/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 new file mode 100644 index 0000000..e945634 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/old/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 @@ -0,0 +1,153 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false)] + [object] + $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VMName = $InputParams.HostName + $Id = $InputParams.Id + $Duration = $InputParams.Duration + + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name } + + switch ($Duration) { + {$Duration -ge 1 -and $Duration -le 7} + { + Write-Verbose "Duration = Snapshot" + $VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*" + + If (@($VMSnapshots).count -eq 1) { + Write-Verbose "Exactly one snapshot match found" + $Taken = $true + $VMSnapshot = $VMSnapshots + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*") + } + else { + if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) { + Write-Error "More than one snapshot match found, abort" + Exit + } + else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" } + } + } + {$Duration -ge 8} + { + Write-Verbose "Duration = Clone" + $VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id) + + If (@($VMClones).count -eq 1) { + Write-Verbose "Exactly one clone match found" + $Taken = $true + $VMClone = $VMClones + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*") + } + else { + if (@($VMClones).count -gt 1) { + Write-Error "More than one VM clone match found, abort" + Exit + } + else { Write-Verbose "Clone Id #$Id match not found for $VMName" } + } + } + Default { + Write-Error "Duration less than zero." + } + } + + If ($Taken -eq $true) { + write-verbose "Updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Taken'; + SnapshotTaken = $Task.PrevRunTime; + AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1]; + AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1]; + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue + } + +} +else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-NewVMSnapshotTask-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-NewVMSnapshotTask-prd.ps1 new file mode 100644 index 0000000..37e2ab8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-NewVMSnapshotTask-prd.ps1 @@ -0,0 +1,237 @@ +# 2021 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=EHlEzPMvDt02gdqMb9wlkdt1FrbmlZjbfQpFTtoIrBc%3d +# content-type application/x-www-form-urlencoded +# 2022 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=%2b6PP2%2bd3FDLqb4bgMs%2b4V1%2bDAMw0tPxN%2f4Ee0eWMa5Q%3d +# + +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL + Method = "Get" + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'VRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtHAKpueFYU4L3N9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirMXTKqtHssnNGBrew3gxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $SPListItem = $ListItems | Where-object Id -eq $InputParams.Id + If ($SPListItem.Title -ne $InputParams.HostName) { + Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname) + Exit + } + + $VMName = $InputParams.HostName + $SnapTime = [DateTime]$SPListItem.DateTime + + $NotifyEmail = $SPListItem.Author.Email + If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail } + + $tryCount = 0 + #while ($tryCount -lt 5) { + try { + $tryCount++ + + + + $SnapName = "AutoSnap_" + $SPListItem.ID + $SnapExpireDateTime = $SnapTime.AddDays($SPListItem.Duration) + If ($SnapExpireDateTime.DayOfWeek -eq "Saturday" -or $SnapExpireDateTime.DayOfWeek -eq "Sunday") { + $SnapExpireDateTime = $SnapExpireDateTime.AddDays(2) + } + $SnapDeleteDateTime = $SnapExpireDateTime.AddDays(2) + + $SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime" + $SnapDescription = "AutoSnap_" + 1080 + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime" + $snapMemory = $false + $snapQuiesce = $false + + Write-Warning $VMName + Write-Warning $SnapName + Write-Warning ("SharePoint: " + $SnapTime) + If ($SnapTime -lt (Get-Date)) { + $SnapTime = (Get-Date).AddSeconds(30) + } + Write-Warning ("PowerShell: " + $SnapTime) + + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name } + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + + $si = Get-View ServiceInstance -Server $VIServer + $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer + + $spec = New-Object VMware.Vim.ScheduledTaskSpec + $spec.Name = $SnapName, $VMname -join '_' + $spec.Description = "$SnapDescription" + $spec.Enabled = $true + $spec.Notification = $NotifyEmail + + $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler + $spec.Scheduler.runat = $SnapTime + + $spec.Action = New-Object VMware.Vim.MethodAction + $spec.Action.Name = "CreateSnapshot_Task" + + @($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object { + $arg = New-Object VMware.Vim.MethodActionArgument + $arg.Value = $_ + $spec.Action.Argument += $arg + } + + # prep for update SharePoint record status + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + # Create vCenter scheduled task + $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec) + Start-Sleep -Seconds 3 + }<# + catch [System.Management.Automation.MethodInvocationException] { + If ($tryCount -lt 4) { + If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") { + Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again") + } + write-warning $trycount + } + Else { + write-error "vCenter Snapshot Scheduled Task Creation failed" + write-error $error[1] + Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov + $Status = "Errored" + exit + } + }#> + catch { + write-error "vCenter Snapshot Scheduled Task Creation failed default message" + write-error $error[1] + Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov + $Status = "Errored" + exit + } + #} + + # update SharePoint record status + If ($Status -ne "Errored") { $Status = "Scheduled" } + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = $Status; + } + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential + } + Invoke-RestMethod @InvokeWebRequestParams + + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 5; + Platform = 'PowerShell-VMware-SnapshotNew'; + } + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) + + Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue +} +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-RemoveVMSnapshot-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-RemoveVMSnapshot-prd.ps1 new file mode 100644 index 0000000..9e3718b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-RemoveVMSnapshot-prd.ps1 @@ -0,0 +1,153 @@ +[CmdletBinding()] +param +( + +) +$StartTime = Get-Date +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' +$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + +Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false +Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + +$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential +$ListToRemove = $SnapshotList | Where-Object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete + +ForEach ($SPRecord in $ListToRemove) { + $Id = $null + $VMName = $null + $SnapName = $null + + $Id = $SPRecord.ID + $VMName = $SPRecord.Title + $SnapName = "AutoSnap_" + $Id + + $SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName + $Datastore = Get-VM $VMName | Get-Datastore + $ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0] + + Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer) + + try { + $SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count + Write-Warning $SnapshotTaskCount + while ($SnapshotTaskCount -ge 1) { + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds." + Start-Sleep -Seconds 60 + + $timestamp = $null + $SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count + Write-Warning $SnapshotTaskCount + } + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal." + $SnapshotToRemove | Remove-Snapshot -Confirm:$false + } + catch { + Write-Error "Snapshot Removal failed"; + Write-Error $Error[1]; + exit + } + + #update SharePoint field + Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)" + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Removed'; + SnapshotRemoved = [datetime](Get-Date); + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams +} +Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue + +$DiffTime = [math]::round((4+((Get-Date) - $StartTime).Minutes),0) +$postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Deprovisioning'; + Units = $DiffTime; + Platform = 'PowerShell-VMware-SnapshotRemove'; +} +Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 new file mode 100644 index 0000000..78774d7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/rb-VMware-UpdateVMSnapshotStatus-prd.ps1 @@ -0,0 +1,202 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false)] + [object] + $WebhookData +) + +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' +$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + +Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false +Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + +$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential +$ListToUpdate = $SnapshotList | where-object { $_.Status -eq "Scheduled" } | Sort-Object DateTime + +#$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +#If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name } + +ForEach($SPRecord in $ListToUpdate) +{ + $VM = $null + $Taken = $null + $VMName = $null + $Duration = $null + $Id = $null + $VMSnapshot = $null + $Task = $null + + If( (($SPRecord.DateTime) -as [datetime]).ToLocalTime() -lt (Get-Date) ) # If datetime has passed + { + $VMName = $SPRecord.Title + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + $Duration = $SPRecord.Duration + $Id = $SPRecord.Id + + switch ($Duration) { + {$Duration -ge 1 -and $Duration -le 7} + { + Write-Verbose "Duration = Snapshot" + $VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*" + + If (@($VMSnapshots).count -eq 1) { + Write-Verbose "Exactly one snapshot match found" + $Taken = $true + $VMSnapshot = $VMSnapshots + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*") + } + else { + if (@($VMSnapshots).count -gt 1) { + Write-Error "More than one snapshot match found, abort" + Exit + } + else { + $Taken = $false + Write-Verbose "Snapshot Id #$Id match not found on $VMName" + Write-Error "Snapshot $Id for $VMName not found." + } + } + } + {$Duration -ge 8} + { + Write-Verbose "Duration = Clone" + $VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id) + + If (@($VMClones).count -eq 1) { + Write-Verbose "Exactly one clone match found" + $Taken = $true + $VMClone = $VMClones + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*") + } + else { + if (@($VMClones).count -gt 1) { + Write-Error "More than one VM clone match found, abort" + Exit + } + else { + $Taken = $false + Write-Verbose "Clone Id #$Id match not found for $VMName" + Write-Error "Clone $Id for $VMName not found." + } + } + } + Default { + Write-Error "Duration less than zero." + } + } + + + write-verbose "Updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + #Status = 'Taken'; + Status = If ($Taken -eq $true) {'Taken'} Else {'Errored'}; + SnapshotTaken = $Task.PrevRunTime; + AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1]; + AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1]; + + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + } +} + +$postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 1; + Platform = 'PowerShell-VMware-SnapshotUpdateStatus'; +} +Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) + +Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/snapshot.json b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/snapshot.json new file mode 100644 index 0000000..06329b0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/snapshot.json @@ -0,0 +1,6 @@ +[ + { + "Id": "575", + "Hostname":"itdfmauditp1.nd.gov" + } +] \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/test.json b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/test.json new file mode 100644 index 0000000..ff024f5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/prod/test.json @@ -0,0 +1,11 @@ +{ + "WebhookName": "rh-VMware-UpdateVMSnapshotStatus-prd", + "RequestBody": "[\n {\n \"Id\": \"68\",\n \"HostName\": \"itddeqappt1.nd.gov\",\n \"DateTime\": \"2/5/2020 7:00 PM\",\n \"Duration\": \"8\",\n \"NotifyEmail\": \"\"\n }\n]", + "RequestHeader": { + "Connection": "Close", + "Expect": "100-continue", + "Host": "s25events.azure-automation.net", + "ITD": "PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p", + "x-ms-request-id": "5ee3253c-5bb4-4aea-a950-6149ddb0436e" + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-RemoveVMSnapshot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-RemoveVMSnapshot.ps1 new file mode 100644 index 0000000..ac9861e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-RemoveVMSnapshot.ps1 @@ -0,0 +1,168 @@ +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $Id = $InputParams.Id + $VMName = $InputParams.Hostname + + $SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential + $Request = $SnapshotList | where-object ID -eq $id + $SnapName = "AutoSnap_" + $Id + + $SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName + $Datastore = Get-VM $VMName | Get-Datastore + $ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0] + + write-warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer) + + + #try { + $SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count + write-warning $SnapshotTaskCount + while ($SnapshotTaskCount -ge 1) { + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds." + Start-Sleep -Seconds 60 + + $timestamp = $null + $SnapshotTaskCount = @(Get-Task | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count + write-warning $SnapshotTaskCount + } + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal." + $SnapshotToRemove | Remove-Snapshot -Confirm:$false -RunAsync + <#} + catch { + Write-Error "Snapshot Removal failed"; + Write-Error $Error[1]; + exit + }#> + + #update SharePoint field + Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Removed'; + SnapshotRemoved = [datetime](Get-Date); + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer -Server * -Confirm:$false +} +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMCloneStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMCloneStatus.ps1 new file mode 100644 index 0000000..15e8e46 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMCloneStatus.ps1 @@ -0,0 +1,128 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false)] + [object] + $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VMName = $InputParams.HostName + $Id = $InputParams.Id + $Duration = $InputParams.Duration + + #$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + + Write-Verbose "Duration = Clone" + $VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id) + + If (@($VMClones).count -eq 1) { + $Taken = $true + $VMClone = $VMClones + } + else { + if (@($VMClones).count -gt 1) { + Write-Error "More than one VM clone match found, abort" + Exit + } + else { Write-Verbose "Clone Id #$Id match not found for $VMName" } + } + + If (@($VMClones).count -eq 1) { + $VMClone = $VMClones + Write-Verbose "Exactly one clone match found, updating SharePoint fields named Status and SnapshotTaken" + + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*") + + If ($Taken -eq $true) { + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $RecordToModify = $ListItems | Where-Object Id -eq $Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Taken'; + SnapshotTaken = $Task.PrevRunTime; + AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1]; + AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1]; + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer * -Confirm:$false + } + } +} +else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMSnapshotStatus-old.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMSnapshotStatus-old.ps1 new file mode 100644 index 0000000..e210edb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/old/rb-VMware-UpdateVMSnapshotStatus-old.ps1 @@ -0,0 +1,127 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false)] + [object] + $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VMName = $InputParams.HostName + $Id = $InputParams.Id + $Duration = $InputParams.Duration + + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name } + + + Write-Verbose "Duration = Snapshot" + $VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*" + + If (@($VMSnapshots).count -eq 1) { + $Taken = $true + $VMSnapshot = $VMSnapshots + } + else { + if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) { + Write-Error "More than one snapshot match found, abort" + Exit + } + else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" } + } + + If (@($VMSnapshots).count -eq 1) { + Write-Verbose "Exactly one snapshot match found, updating SharePoint fields named Status and SnapshotTaken" + + If ($Taken -eq $true) { + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Taken'; + SnapshotTaken = $VMSnapshot.Created; + AutoExpire = ($VMSnapshot.Description -split '[\r\n]+')[1].split('_')[1]; + AutoDelete = ($VMSnapshot.Description -split '[\r\n]+')[2].split('_')[1]; + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer * -Confirm:$false + } + } +} +else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-NewVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-NewVMSnapshotTask.ps1 new file mode 100644 index 0000000..778652d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-NewVMSnapshotTask.ps1 @@ -0,0 +1,216 @@ +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [object] $WebhookData +) + +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL + Method = "Get" + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'HAKpueFYU4L3NMXTKqtHssnNGBrew3gVRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkir') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List2 = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $SPListItem = $ListItems | Where-object Id -eq $InputParams.Id + If ($SPListItem.Title -ne $InputParams.HostName) { + Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname) + Exit + } + + $VMName = $InputParams.HostName + $SnapTime = ([DateTime]$SPListItem.DateTime).AddMinutes($Duration * 3) + + $NotifyEmail = $SPListItem.Author.Email + If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail } + + $tryCount = 0 +# while ($tryCount -lt 5) { + try { + $tryCount++ + Write-Warning ("SharePoint: " + $SnapTime) + If ($SnapTime -lt (Get-Date)) { + $SnapTime = (Get-Date).AddSeconds(30) + } + Write-Warning ("PowerShell: " + $SnapTime) + + $SnapName = "AutoSnap_" + $SPListItem.ID + $SnapExpireDateTime = $SnapTime.AddMinutes($SPListItem.Duration * 3) + $SnapDeleteDateTime = $SnapExpireDateTime.AddMinutes(30) + + $SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime" + $snapMemory = $false + $snapQuiesce = $false + + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name } + + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + + $si = Get-View ServiceInstance -Server $VIServer + $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer + + $spec = New-Object VMware.Vim.ScheduledTaskSpec + $spec.Name = $SnapName, $VMname -join '_' + $spec.Description = "$SnapDescription" + $spec.Enabled = $true + $spec.Notification = $NotifyEmail + + $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler + $spec.Scheduler.runat = $SnapTime + + $spec.Action = New-Object VMware.Vim.MethodAction + $spec.Action.Name = "CreateSnapshot_Task" + + @($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object { + $arg = New-Object VMware.Vim.MethodActionArgument + $arg.Value = $_ + $spec.Action.Argument += $arg + } + + # prep for update SharePoint record status + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + # Create vCenter scheduled task + $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec) + Start-Sleep -Seconds 3 + } + catch [System.Management.Automation.MethodInvocationException] { + If ($tryCount -lt 4) { + If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") { + Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again") + } + write-warning $trycount + } + Else { + write-error "vCenter Snapshot Scheduled Task Creation failed" + write-error $error[1] + Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov + $Status = "Errored" + exit + } + } + catch { + write-error "vCenter Snapshot Scheduled Task Creation failed default message" + write-error $error[1] + Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov + $Status = "Errored" + exit + } + #} + + # update SharePoint record status + If ($Status -ne "Errored") { $Status = "Scheduled" } + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = $Status; + } + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer -Server * -Confirm:$false +} +Else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-RemoveVMSnapshot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-RemoveVMSnapshot.ps1 new file mode 100644 index 0000000..1d3cd72 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-RemoveVMSnapshot.ps1 @@ -0,0 +1,164 @@ +[CmdletBinding()] +param +( + +) + +function Get-ITDVMwareSharePointSnapshotRequestList { + [CmdletBinding()] + Param + ( + [PSCredential] + $Credential + ) + + begin { + $InvokeWebRequestParams = @{ } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + + $URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id' + $InvokeWebRequestParams += @{ + Uri = $URL; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" } + } + + $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json + } + + process { + + } + + end { + $List.d.results + } +} +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential + $ListToRemove = $SnapshotList | where-object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete + + ForEach ($SPRecord in $ListToRemove) { + $Id = $null + $VMName = $null + $SnapName = $null + + $Id = $SPRecord.ID + $VMName = $SPRecord.Title + $SnapName = "AutoSnap_" + $Id + + $SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName + $Datastore = Get-VM $VMName | Get-Datastore + $ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0] + + Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer) + + try { + $SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count + Write-Warning $SnapshotTaskCount + while ($SnapshotTaskCount -ge 1) { + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds." + Start-Sleep -Seconds 60 + + $timestamp = $null + $SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count + Write-Warning $SnapshotTaskCount + } + $timestamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal." + $SnapshotToRemove | Remove-Snapshot -Confirm:$false + } + catch { + Write-Error "Snapshot Removal failed"; + Write-Error $Error[1]; + exit + } + + #update SharePoint field + Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + #$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + #If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break } + #$IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Removed'; + SnapshotRemoved = [datetime](Get-Date); + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + } + Disconnect-VIServer -Server * -Confirm:$false +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-UpdateVMSnapshotStatus.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-UpdateVMSnapshotStatus.ps1 new file mode 100644 index 0000000..e310030 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/rb-VMware-UpdateVMSnapshotStatus.ps1 @@ -0,0 +1,153 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false)] + [object] + $WebhookData +) + +If ($WebhookData) { + If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') { + Write-Verbose "Header has required data" + } + Else { + Write-Error "Header missing required data" + exit; + } + + $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody) + $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' + $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential + + $VMName = $InputParams.HostName + $Id = $InputParams.Id + $Duration = $InputParams.Duration + + $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name } + + switch ($Duration) { + {$Duration -ge 1 -and $Duration -le 7} + { + Write-Verbose "Duration = Snapshot" + $VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*" + + If (@($VMSnapshots).count -eq 1) { + Write-Verbose "Exactly one snapshot match found" + $Taken = $true + $VMSnapshot = $VMSnapshots + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*") + } + else { + if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) { + Write-Error "More than one snapshot match found, abort" + Exit + } + else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" } + } + } + {$Duration -ge 8} + { + Write-Verbose "Duration = Clone" + $VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id) + + If (@($VMClones).count -eq 1) { + Write-Verbose "Exactly one clone match found" + $Taken = $true + $VMClone = $VMClones + $Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*") + } + else { + if (@($VMClones).count -gt 1) { + Write-Error "More than one VM clone match found, abort" + Exit + } + else { Write-Verbose "Clone Id #$Id match not found for $VMName" } + } + } + Default { + Write-Error "Duration less than zero." + } + } + + If ($Taken -eq $true) { + write-verbose "Updating SharePoint fields named Status and SnapshotTaken" + $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + $InvokeWebRequestParams = @{ + Uri = $UrlListItem; + Method = "Get"; + UseBasicParsing = $true; + Headers = @{ "Accept" = "application/json;odata=verbose" }; + Credential = $SharePointCredential + } + $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + "IF-MATCH" = '*' + "X-HTTP-Method" = "MERGE" + } + + $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id + If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break } + $IDtoModify = $RecordToModify.ID + + $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)" + $InvokeWebRequestParams = @{ + Uri = $UrlItem; + Method = "Get"; + Headers = @{ "Accept" = "application/json;odata=verbose" } + UseBasicParsing = $true; + Credential = $SharePointCredential + } + + [PSCustomObject]$SetRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName }; + Status = 'Taken'; + SnapshotTaken = $Task.PrevRunTime; + AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1]; + AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1]; + } + + $body = $SetRecord | ConvertTo-Json + $InvokeWebRequestParams = @{ + + Uri = $UrlItem; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + Credential = $SharePointCredential; + } + Invoke-RestMethod @InvokeWebRequestParams + + Disconnect-VIServer * -Confirm:$false + } + +} +else { + Write-Error "Runbook must be started from webhook" +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/snapshot.json b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/snapshot.json new file mode 100644 index 0000000..d833349 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/snapshot.json @@ -0,0 +1,8 @@ +[ + { + "Id": "{ItemProperty:ID}", + "HostName": "{ItemProperty:HostName}", + "DateTime": "{ItemProperty:DateTime}", + "Duration": "{ItemProperty:Duration}" + } +] \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/test.json b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/test.json new file mode 100644 index 0000000..c0a0266 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Runbook/VMSnapshots/test/test.json @@ -0,0 +1,6 @@ +[ + { + "Id": "566", + "HostName": "itdscmt1.nd.gov" + } +] \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/ITD.SRM.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/ITD.SRM.psm1 new file mode 100644 index 0000000..e28e193 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/ITD.SRM.psm1 @@ -0,0 +1,655 @@ +function Import-ITDVMwareSRMExport { + [CmdletBinding()] + Param + ( + [string] + $Path + ) + + begin { + + } + + process { + [xml]$Global:SrmXml = Get-Content -Path $Path + } + + end { + + } +} + +function Get-ITDVMwareSRMDatacenter { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + ((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter | Where-Object id -EQ $i) + } + } + 'Name' { + ForEach ($n in $Name) { + ((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter | Where-Object name -Like "*$n*") + } + } + 'Default' { + ((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter ) + } + } + } + + end { + + } +} +function Get-ITDVMwareSRMVMFolder { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + $VMInventoryFolders = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.InventoryFolder + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + $VMInventoryFolders | Where-Object id -Like "*$i*" + } + } + 'Name' { + ForEach ($n in $Name) { + $VMInventoryFolders | Where-Object name -Like "*$n*" + } + } + 'Default' { + $VMInventoryFolders + } + } + } + + end { + } +} + +function Get-ITDVMwareSRMHostFolder { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + Foreach ($i in $Id) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder | Where-Object id -EQ $i + } + } + 'Name' { + Foreach ($i in $Id) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder | Where-Object name -Like "*$n*" + } + + } + 'Default' { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder + } + } + + + } + end { + + } +} +function Get-ITDVMwareSRMComputeResource { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'ResPoolId')] + [string[]] + $ResPoolId, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.id -like "*$i*" } + } + } + 'ResPoolId' { + ForEach ($i in $ResPoolId) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.resourcepool.id -like "*$i*" } + } + } + 'Name' { + If ($Name) { + ForEach ($n in $Name) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.name -like "*$n*" } + } + } + Else { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource + } + } + 'Default' { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource + } + } + } + + end { + + } +} + +function Get-ITDVMwareSRMVMHost { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts | Where-Object { $_.id -like "*$i*" } + } + } + 'Name' { + ForEach ($n in $Name) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts | Where-Object { $_.name -like "*$n*" } + } + } + 'Default' { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts + } + } + + } + + end { + + } +} + +function Get-ITDVMwareSRMDatastore { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore | Where-Object id -Like "*$i*" + } + } + 'Name' { + ForEach ($n in $Name) { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore | Where-Object { $_.name -like "*$n*" } + } + } + 'Default' { + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore + } + } + } + + end { + + } +} + +function Get-ITDVMwareSRMNetwork { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + $dvportgrouplist = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + #(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup | Where-Object { $_.id -eq "*$i*" } + $dvportgrouplist | where-object id -eq $i + } + } + 'Name' { + ForEach ($n in $Name) { + #(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup | Where-Object { $_.name -eq "*$n*" } + $dvportgrouplist | where-object name -eq $n + } + } + 'Default' { + $dvportgrouplist + } + } + } + end { + + } +} + +function Get-ITDVMwareSRMVM { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name + ) + + begin { + + } + + process { + $VMInventory = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.VirtualMachine + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.InventoryFolder.VirtualMachine + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + ForEach ($i in $Id) { + $VMInventory | Where-Object { $_.id -like "*$i*" } + } + } + 'Name' { + ForEach ($n in $Name) { + $VMInventory | Where-Object { $_.name -like "*$n*" } + } + } + <#'Default' { + $VMInventory + }#> + } + } + + end { + + } +} + +function Get-ITDVMwareSRMProtectionGroup { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [Parameter(ParameterSetName = 'Name')] + [string[]] + $Name, + + [switch] + $Detailed, + + [ValidateScript( { $Detailed -eq $true })] + [switch] + $Formatted + ) + + begin { + + } + + process { + $ProtectionGroups = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ "ProtectionGroups").Attributes.Folder.vmProtectionGroup + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + $ProtectionGroupsSearch = $Id | ForEach-Object { + $ProtectionGroups | Where-Object Id -Like "*$_*" + } + } + 'Name' { + $ProtectionGroupsSearch = $Name | ForEach-Object { + $ProtectionGroups | Where-Object Name -Like "*$_*" + } + } + 'Default' { + $ProtectionGroupsSearch = $ProtectionGroups + } + } + + $AllVrDatastores = Get-ChildItem -Path "vmstores:\itdvmvc2.nd.gov@443\Secondary Datacenter\" | Where-Object Name -Like "*_VR*" + $VrFolders = $AllVrDatastores | Get-ChildItem | Where-Object ItemType -EQ "Folder" + + If ($Detailed) { + $DetailedResult = [System.Collections.ArrayList]@() + ForEach ($ProtectionGroup in $ProtectionGroupsSearch) { + Write-Warning -Message ("Start Protection Group Loop for " + $ProtectionGroup.Name.TrimStart().TrimEnd() ) + $AbrDatastores = $null + If ($ProtectionGroup.datastores) { + $AbrDatastores = Get-ITDVMwareSRMDatastore -Id ($ProtectionGroup.datastores | select -Unique).TrimStart().TrimEnd() + } + Else { + $AbrDatastores = $null + } + + $VMs = (Get-ITDVMwareSRMVM -Id ($ProtectionGroup.ProtectionProperties.id)).Name + $VrDatastores = [System.Collections.ArrayList]@() + ForEach ($VM in $VMs) { + $null = $VRDatastores.add( ($VRFolders | Where-Object Name -Like "$VM*").Datastore) + } + $VrDatastores = $VRDatastores | Select-Object -Unique Name + + + $PGobj = [PSCustomObject]@{ + Name = $ProtectionGroup.Name.TrimStart().TrimEnd(); + ReplicationType = $ProtectionGroup.ReplicationProviderType.TrimStart().TrimEnd(); + ArrayPairKey = ( $ProtectionGroup.arrayPairKey | ForEach-Object { If ($_.GetType().Name -eq 'String') { $_.TrimStart().TrimEnd() } } | Select-Object -Unique ) + Folder = ( Get-ITDVMwareSRMVMFolder -Id ($ProtectionGroup.ProtectionProperties.folder | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd(); + ResourceGroup = ( Get-ITDVMwareSRMComputeResource -ResPoolId ($ProtectionGroup.ProtectionProperties.resourceGroup | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd(); + Network = ( Get-ITDVMwareSRMNetwork -Id ($ProtectionGroup.ProtectionProperties.RecoveryLocationSettings.DeviceInfo.NetworkDeviceBacking.network | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd(); + AbrDatastores = If ($AbrDatastores -ne $null) { ($AbrDatastores.name.TrimStart().TrimEnd() ) }; + VrDatastores = $VrDatastores.Name | Select-Object -Unique + VM = ( Get-ITDVMwareSRMVM -Id ($ProtectionGroup.ProtectionProperties.id.TrimStart().TrimEnd()) ).Name.TrimStart().TrimEnd(); + } + $null = $DetailedResult.add($PGobj) + } + + If ($Formatted) { + $FormattedResult = $DetailedResult | select Name, ReplicationType, ArrayPairKey, ` + @{n = 'Folder'; e = { ($_.Folder | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = "ResourceGroup"; e = { ($_.ResourceGroup | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = "Network"; e = { ($_.Network | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'AbrDatastores'; e = { ($_.AbrDatastores | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'VrDatastores'; e = { ($_.VrDatastores | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'VM'; e = { ($_.VM | Sort-Object | Out-String).TrimEnd() } } + } + } + } + end { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + If ($Detailed) { + If ($Formatted) { + Write-Output $FormattedResult + } + else { + Write-Output $DetailedResult + } + } + Else { + Write-Output $ProtectionGroupsSearch + } + } + 'Name' { + If ($Detailed) { + If ($Formatted) { + Write-Output $FormattedResult + } + else { + Write-Output $DetailedResult + } + } + Else { + Write-Output $ProtectionGroupsSearch + } + } + 'Default' { + If ($Detailed) { + If ($Formatted) { + Write-Output $FormattedResult + } + else { + Write-Output $DetailedResult + } + } + Else { + Write-Output $ProtectionGroups + } + } + } + } +} + +function Get-ITDVMwareSRMVMSettings { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = 'Id')] + [string[]] + $Id, + + [CmdletBinding(DefaultParameterSetName = 'Default')] + [switch] + $Detailed + ) + + begin { + + } + + process { + switch ($PsCmdlet.ParameterSetName) { + 'Id' { + $VMSettingsSearch = $Id | ForEach-Object { + ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ VMSettings).Attributes.VMSettings | Where-Object Id -Like "*$_*" + } + + } + 'Default' { + $VMSettingsSearch = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ VMSettings).Attributes.VMSettings + } + } + + If ($Detailed) { + $DetailedResult = [System.Collections.ArrayList]@() + ForEach ($VMSetting in $VMSettingsSearch) { + $VMSettingObj = [PSCustomObject]@{ + Id = $VMSetting.id.TrimStart().TrimEnd(); + Name = (Get-ITDVMwareSRMVM -Id $VMSetting.Id.TrimStart().TrimEnd()).Name.TrimStart().TrimEnd(); + #recoveryPriority = $VMSetting.recoveryPriority; + recoveryPriorityGui = switch ($VMSetting.recoveryPriority.TrimStart().TrimEnd()) { + 25 { 1 } + 40 { 2 } + 50 { 3 } + 60 { 4 } + 75 { 5 } + } + } + $null = $DetailedResult.add($VMSettingObj) + } + } + + } + + end { + If ($Detailed) { + Write-Output $DetailedResult + } + Else { + $VMSettingsSearch + } + } +} + +function Get-ITDVMwareSRMRecoveryPlan { + [CmdletBinding()] + param ( + [string[]] + $Name, + + [switch] + $Formatted + ) + + begin { + + } + + process { + $RecoveryPlans = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ RecoveryPlans).Attributes.Folder.RecoveryPlan + If ($Name) { + $RecoveryPlansSearch = $Name | ForEach-Object { + $RecoveryPlans | Where-Object name -Like "*$_*" + } + } + else { + $RecoveryPlansSearch = $RecoveryPlans + } + $DetailedResult = [System.Collections.ArrayList]@() + ForEach ($RecoveryPlan in $RecoveryPlansSearch) { + Write-Warning -Message ("Start Recovery Plan Loop for " + $RecoveryPlan.Name.TrimStart().TrimEnd() ) + $ProtectionGroupDetailed = Get-ITDVMwareSRMProtectionGroup -Id $RecoveryPlan.protectionGroups.TrimStart().TrimEnd() -Detailed + + $AbrDatastores = $ProtectionGroupDetailed.AbrDatastores | Select-Object -Unique | Sort-Object + $VrDatastores = $ProtectionGroupDetailed.VrDatastores | Select-Object -Unique | Sort-Object + $Network = $ProtectionGroupDetailed.Network | Select-Object -Unique | Sort-Object + + $VMSettings = Get-ITDVMwareSRMVMSettings -Id (Get-ITDVMwareSRMVM -Name $ProtectionGroupDetailed.VM).Id.TrimStart().TrimEnd() -Detailed + If ($RecoveryPlan.Callouts) { + $Callouts = [System.Collections.ArrayList]@() + $RecoveryPlan.Callouts.CalloutSpec | ForEach-Object { + + } + } + + $RPobj = [PSCustomObject]@{ + Name = $RecoveryPlan.Name.TrimStart().TrimEnd(); + ProtectionGroups = $ProtectionGroupDetailed.Name | Sort-Object; + Network = $Network; + AbrDatastores = $AbrDatastores; + VrDatastores = $VrDatastores; + BeforePriority1 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority1Vms').RecoveryPrompt | select promptText, Description + Priority1VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 1).Name; + BeforePriority2 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority2Vms').RecoveryPrompt | select promptText, Description + Priority2VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 2).Name; + BeforePriority3 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority3Vms').RecoveryPrompt | select promptText, Description + Priority3VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 3).Name; + BeforePriority4 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority4Vms').RecoveryPrompt | select promptText, Description + Priority4VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 4).Name; + BeforePriority5 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority5Vms').RecoveryPrompt | select promptText, Description + Priority5VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 5).Name; + } + + $null = $DetailedResult.Add($RPobj) + } + + If ($Formatted) { + $FormattedResult = $DetailedResult | select Name, ` + @{n = 'ProtectionGroups'; e = { ($_.ProtectionGroups | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'Network'; e = { ($_.Network | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'AbrDatastores'; e = { ($_.AbrDatastores | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'VrDatastores'; e = { ($_.VrDatastores | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'BeforePriority1'; e = { $_.BeforePriority1 | Out-String } }, ` + @{n = 'Priority1VMs'; e = { ($_.Priority1VMs | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'BeforePriority2'; e = { $_.BeforePriority2 | Out-String } }, ` + @{n = 'Priority2VMs'; e = { ($_.Priority2VMs | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'BeforePriority3'; e = { $_.BeforePriority3 | Out-String } }, ` + @{n = 'Priority3VMs'; e = { ($_.Priority3VMs | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'BeforePriority4'; e = { $_.BeforePriority4 | Out-String } }, ` + @{n = 'Priority4VMs'; e = { ($_.Priority4VMs | Sort-Object | Out-String).TrimEnd() } }, ` + @{n = 'BeforePriority5'; e = { $_.BeforePriority5 | Out-String } }, ` + @{n = 'Priority5VMs'; e = { ($_.Priority5VMs | Sort-Object | Out-String).TrimEnd() } } + } + } + + end { + If ($Formatted) { + Write-Output $FormattedResult + } + Else { + Write-Output $DetailedResult + } + } +} + + +function Get-ITDVMwareSRMMasterPlan { + [CmdletBinding()] + param ( + + ) + + begin { + $RecoveryPlans = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ RecoveryPlans).Attributes.Folder.RecoveryPlan + } + + process { + + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/SRMExportExample.xml b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/SRMExportExample.xml new file mode 100644 index 0000000..5a543df --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/SRM/SRMExportExample.xml @@ -0,0 +1,43130 @@ + + + + + + + false + r_datastore_datastore-9690 + r_datastore_datastore-9695 + r_datastore_datastore-9696 + r_datastore_datastore-9697 + r_datastore_datastore-9698 + r_datastore_datastore-9720 + r_datastore_datastore-9725 + r_datastore_datastore-9731 + r_datastore_datastore-9746 + + + true + l_datastore_datastore-13868 + l_datastore_datastore-13876 + l_datastore_datastore-13896 + l_datastore_datastore-13899 + l_datastore_datastore-13906 + l_datastore_datastore-13917 + l_datastore_datastore-13921 + l_datastore_datastore-13925 + l_datastore_datastore-13963 + + + + + + + itdmdna9k.nd.gov + + itdmdna9000 + itdbisa9000 + + + IBM Spectrum Accelerate Family SRA + IBM XIV + IBM Spectrum Accelerate + IBM FlashSystem A9000/A9000R + IBM Corp. + 3.0.1 + + IBM XIV Remote Mirroring + 10.2 + + + IBM XIV Remote Mirroring + 11 + + + IBM FlashSystem A9000/A9000R Remote Mirroring + 12 + + + + XIV +
+ ip1 + 10.8.38.123 +
+
+ ip2 + 10.8.38.124 +
+
+ ip3 + 0.0.0.0 +
+
+ false +
+ + itdbisa9k.nd.gov + + itdbisa9000 + itdmdna9000 + + + IBM Spectrum Accelerate Family SRA + IBM XIV + IBM Spectrum Accelerate + IBM FlashSystem A9000/A9000R + IBM Corp. + 3.0.1 + + IBM XIV Remote Mirroring + 10.2 + + + IBM XIV Remote Mirroring + 11 + + + IBM FlashSystem A9000/A9000R Remote Mirroring + 12 + + + + XIV +
+ ip1 + 10.8.38.121 +
+
+ ip2 + 10.8.38.122 +
+
+ ip3 + 0.0.0.0 +
+
+ true +
+
+
+ + + + _recoveryRoot + + 20191207 BND Test 1 FIS + vmGroup + pg_vm-protection-group-138658046 + false + + r_network_dvportgroup-414 + r_network_dvportgroup-414 + + + + 20191207 BND Test 2 HELMS & PitneyBowes + vmGroup + pg_vm-protection-group-138660050 + pg_vm-protection-group-138661194 + false + + r_network_dvportgroup-24535 + r_network_dvportgroup-24535 + + + r_network_dvportgroup-639 + r_network_dvportgroup-639 + + + + 20191207 BND Test 3 SQL Apps + vmGroup + pg_vm-protection-group-138657897 + pg_vm-protection-group-138660555 + pg_vm-protection-group-138661758 + pg_vm-protection-group-138661896 + pg_vm-protection-group-138662345 + pg_vm-protection-group-138683359 + false + + r_network_dvportgroup-201 + r_network_dvportgroup-201 + + + r_network_dvportgroup-417 + r_network_dvportgroup-417 + + + r_network_dvportgroup-494 + r_network_dvportgroup-494 + + + r_network_dvportgroup-641 + r_network_dvportgroup-641 + + + r_network_dvportgroup-642 + r_network_dvportgroup-642 + + + r_network_dvportgroup-644 + r_network_dvportgroup-644 + + + r_network_dvportgroup-686 + r_network_dvportgroup-686 + + + + 20191207 BND Test 4 WebSphere + vmGroup + pg_vm-protection-group-138684035 + false + + r_network_dvportgroup-614 + r_network_dvportgroup-614 + + + + 20191207 BND Test 5 MFA + vmGroup + pg_vm-protection-group-138660836 + false + + r_network_dvportgroup-550 + r_network_dvportgroup-550 + + + + 20200108 BND Test 1 PitneyBowes + vmGroup + pg_vm-protection-group-138661194 + false + + r_network_dvportgroup-462 + r_network_dvportgroup-462 + + + r_network_dvportgroup-24535 + r_network_dvportgroup-24535 + + + + Tier 1B P1 + vmGroup + pg_vm-protection-group-138691475 + pg_vm-protection-group-138695658 + false + + + Tier 1D Infra-Security-MFA-Azure + vmGroup + pg_vm-protection-group-154783448 + false + + + Tier 1D P1 + vmGroup + pg_vm-protection-group-138673423 + pg_vm-protection-group-138699710 + pg_vm-protection-group-138691726 + pg_vm-protection-group-138742322 + false + + + Tier 1E Infra-Monitoring-Solarwinds + vmGroup + pg_vm-protection-group-138677009 + pg_vm-protection-group-138694707 + false + + + Tier 2A Infra-LoadBalancer + vmGroup + pg_vm-protection-group-138694251 + false + + + Tier 2A Infra-Proxy + vmGroup + pg_vm-protection-group-138697581 + false + r_vm_vm-2199 + + + Tier 2A P1 + vmGroup + pg_vm-protection-group-138657742 + pg_vm-protection-group-138660836 + pg_vm-protection-group-138662975 + pg_vm-protection-group-138689538 + pg_vm-protection-group-138691926 + pg_vm-protection-group-138692324 + pg_vm-protection-group-138693089 + pg_vm-protection-group-138696727 + pg_vm-protection-group-152827990 + pg_vm-protection-group-162752054 + pg_vm-protection-group-162812983 + false + + + Tier 2B P1 + vmGroup + pg_vm-protection-group-138665700 + pg_vm-protection-group-138669827 + pg_vm-protection-group-138691078 + pg_vm-protection-group-138697452 + pg_vm-protection-group-138698683 + false + + + Tier 3A BND-FIS + vmGroup + pg_vm-protection-group-138658046 + false + + + Tier 3A BND-FUNDTECH + vmGroup + pg_vm-protection-group-138659675 + false + + + beforeRecoverPriority2Vms + + Change IP - bnd0425, ` + Change IP + + + + + + Tier 3A BND-Fiserv + vmGroup + pg_vm-protection-group-162751055 + false + + + Tier 3A BND-HELMS + vmGroup + pg_vm-protection-group-138660050 + false + + + Tier 3A BND-SQL + vmGroup + pg_vm-protection-group-138657897 + pg_vm-protection-group-138660555 + pg_vm-protection-group-138661758 + pg_vm-protection-group-138661896 + pg_vm-protection-group-138662345 + pg_vm-protection-group-138683359 + false + + + Tier 3A ERN-PERSLink + vmGroup + pg_vm-protection-group-138690322 + pg_vm-protection-group-138690883 + false + r_vm_vm-2091 + r_vm_vm-2230 + + + Tier 3A P1 + vmGroup + pg_vm-protection-group-138661194 + pg_vm-protection-group-138680357 + pg_vm-protection-group-138684420 + pg_vm-protection-group-138689417 + pg_vm-protection-group-138689858 + pg_vm-protection-group-138691605 + pg_vm-protection-group-138692888 + pg_vm-protection-group-138699831 + pg_vm-protection-group-138666317 + pg_vm-protection-group-138695111 + pg_vm-protection-group-154782519 + false + + + Tier 3A Shared-WebSphere + vmGroup + pg_vm-protection-group-138681369 + false + r_vm_vm-1187 + r_vm_vm-1191 + r_vm_vm-1188 + r_vm_vm-1186 + r_vm_vm-1221 + r_vm_vm-1276 + r_vm_vm-1216 + r_vm_vm-1184 + + + Tier 3B DHS-MMIS-EDIFECS + vmGroup + pg_vm-protection-group-138666036 + false + + + Tier 3B DHS-MMIS-MoveIT + vmGroup + pg_vm-protection-group-138666238 + false + + + Tier 3B P1 + vmGroup + pg_vm-protection-group-138695448 + false + + + Tier 4A CJIS-LERMS + vmGroup + pg_vm-protection-group-138662563 + false + + + Tier 4A Shared-EDMS + vmGroup + pg_vm-protection-group-138679015 + pg_vm-protection-group-138692523 + pg_vm-protection-group-138693471 + pg_vm-protection-group-138694134 + pg_vm-protection-group-138694461 + pg_vm-protection-group-138694586 + false + + + Tier 4B DHS-MMIS-Cognos + vmGroup + pg_vm-protection-group-138665957 + false + + + Tier 4B DHS-MMIS-Xpressions + vmGroup + pg_vm-protection-group-138666613 + false + + + Tier 4B DHS-Mediclaim + vmGroup + pg_vm-protection-group-138665883 + false + + + Tier 4B DHS-SPACES + vmGroup + pg_vm-protection-group-138666854 + false + + + Tier 4B P1 + vmGroup + pg_vm-protection-group-138666159 + pg_vm-protection-group-138666429 + pg_vm-protection-group-138666547 + pg_vm-protection-group-138666692 + false + r_vm_vm-2587 + + + Tier 4B Shared-PeopleSoft-HigherEd + vmGroup + pg_vm-protection-group-154764253 + false + + + Tier 4B Shared-PeopleSoft-State + vmGroup + pg_vm-protection-group-152818450 + false + + + Tier 4C DHS-Orchard + vmGroup + pg_vm-protection-group-138666762 + false + + + Tier 4C ITD-GIS-HUB + vmGroup + pg_vm-protection-group-138696447 + false + + + Tier 4C ITD-Workforce + vmGroup + pg_vm-protection-group-138696038 + false + + + Tier 4C Infra-Servers-SCCM + vmGroup + pg_vm-protection-group-138698833 + false + + + Tier 4C P1 + vmGroup + pg_vm-protection-group-138660693 + pg_vm-protection-group-138660997 + pg_vm-protection-group-138661131 + pg_vm-protection-group-138661408 + pg_vm-protection-group-138672968 + pg_vm-protection-group-138676866 + pg_vm-protection-group-138677562 + pg_vm-protection-group-138677696 + pg_vm-protection-group-138678600 + pg_vm-protection-group-138679955 + pg_vm-protection-group-138680552 + pg_vm-protection-group-138680669 + pg_vm-protection-group-138681170 + pg_vm-protection-group-138684535 + pg_vm-protection-group-138684771 + pg_vm-protection-group-138684886 + pg_vm-protection-group-138685455 + pg_vm-protection-group-138686935 + pg_vm-protection-group-138686986 + pg_vm-protection-group-138687183 + pg_vm-protection-group-138687300 + pg_vm-protection-group-138687410 + pg_vm-protection-group-138689060 + pg_vm-protection-group-138689659 + pg_vm-protection-group-138690051 + pg_vm-protection-group-138693278 + pg_vm-protection-group-138694982 + pg_vm-protection-group-138695319 + pg_vm-protection-group-138695775 + pg_vm-protection-group-138695902 + pg_vm-protection-group-138696320 + pg_vm-protection-group-138698558 + pg_vm-protection-group-138699051 + pg_vm-protection-group-138699956 + pg_vm-protection-group-138700551 + pg_vm-protection-group-138725393 + pg_vm-protection-group-138684035 + pg_vm-protection-group-138685578 + pg_vm-protection-group-138686267 + pg_vm-protection-group-143332324 + pg_vm-protection-group-152813946 + pg_vm-protection-group-152817573 + pg_vm-protection-group-152826900 + pg_vm-protection-group-152828115 + pg_vm-protection-group-162751766 + pg_vm-protection-group-162752260 + false + r_vm_vm-2437 + r_vm_vm-28884 + + + Tier 4C SOS-CentralIndexing + vmGroup + pg_vm-protection-group-138662034 + false + r_vm_vm-2384 + r_vm_vm-2385 + r_vm_vm-2420 + r_vm_vm-2452 + + + Tier 4C Shared-Powerschool + vmGroup + pg_vm-protection-group-138683706 + false + + + Tier 4C Shared-Voice + vmGroup + pg_vm-protection-group-138662491 + pg_vm-protection-group-138683242 + pg_vm-protection-group-138684652 + pg_vm-protection-group-138685010 + pg_vm-protection-group-162752832 + false + + + Tier 4D P1 + vmGroup + pg_vm-protection-group-138691197 + false + + + Tier 5A Infra-Security-CertificateAuthority + vmGroup + pg_vm-protection-group-138699198 + false + + + Tier 5A P1 + vmGroup + pg_vm-protection-group-138677415 + pg_vm-protection-group-138686014 + pg_vm-protection-group-152827369 + false + + + + + + + + false + + connections.hmsPanicDelay + 5 + + + connections.hmsPingFailedDelay + 2 + + + connections.waitForUpdatesTimeout + 900 + + + exportHistory.numReports + 5 + + + localSiteStatus.checkInterval + 60 + + + localSiteStatus.eventFrequency + 600 + + + localSiteStatus.maxClockSkew + 20 + + + localSiteStatus.maxCpuUsage + 70 + + + localSiteStatus.minCertRemainingTime + 30 + + + localSiteStatus.minDiskSpace + 100 + + + localSiteStatus.minMemory + 32 + + + logManager.Default + verbose + + + logManager.ExternalAPI + verbose + + + logManager.HbrProvider + verbose + + + logManager.IPCustomizer + verbose + + + logManager.InventoryMapper + verbose + + + logManager.Licensing + verbose + + + logManager.Persistence + verbose + + + logManager.Recovery + verbose + + + logManager.RecoveryConfig + verbose + + + logManager.Replication + verbose + + + logManager.ServerAuthorization + verbose + + + logManager.SessionManager + verbose + + + logManager.SoapAdapter + info + + + logManager.Storage + verbose + + + logManager.StorageProvider + verbose + + + recovery.autoDeployGuestAlias + true + + + recovery.customizationShutdownTimeout + 300 + + + recovery.customizationTimeout + 600 + + + recovery.defaultPriority + 3 + + + recovery.forceRecovery + false + + + recovery.hostPowerOnTimeout + 1200 + + + recovery.powerOffTimeout + 300 + + + recovery.powerOnDelay + 0 + + + recovery.powerOnTimeout + 300 + + + recovery.skipGuestShutdown + false + + + recovery.useIpMapperAutomatically + true + + + remoteManager.defaultTimeout + 900 + + + remoteManager.enableCustomFields + true + + + remoteManager.powerOnAggregationInterval + 2000 + + + remoteManager.taskCancelDefaultTimeout + 300 + + + remoteManager.taskDefaultTimeout + 900 + + + remoteManager.taskProgressDefaultTimeout + 180 + + + remoteManager.xVcVMotionTimeout + 3600 + + + remoteSiteStatus.drPanicDelay + 5 + + + remoteSiteStatus.drPingFailedDelay + 2 + + + replication.disablePiggybackVmsCheckDuringDeactivate + false + + + replication.placeholderVmCreationTimeout + 300 + + + replication.pollForMissingInventoryMappings + false + + + replication.protectionInfoSyncTimeout + 900 + + + replication.protectionPollInterval + 120 + + + sso.sts.tokenLifetime + 28800 + + + storage.attachTagsDelaySec + 30 + + + storage.commandTimeout + 300 + + + storage.datastoreMonitoringPollingInterval + 30 + + + storage.enableSdrsStandardTagCategoryCreation + true + + + storage.enableSdrsTagging + true + + + storage.enableSdrsTaggingRepair + true + + + storage.maxConcurrentCommandCnt + 5 + + + storage.minDsGroupComputationInterval + 0 + + + storage.querySyncStatusPollingInterval + 30 + + + storage.sdrsTaggingPollInterval + 50 + + + storage.storagePingInterval + 86400 + + + storage.syncTimeout + 86400 + + + storagePolicyAbrReplication.policyDatastorePollInterval + 20 + + + storageProvider.autoDetachLUNsWithDuplicateVolume + true + + + storageProvider.autoResignatureMode + 0 + + + storageProvider.batchAttachTimeoutSec + 3600 + + + storageProvider.batchDetachTimeoutSec + 3600 + + + storageProvider.batchMountTimeoutSec + 3600 + + + storageProvider.batchUnmountTimeoutSec + 3600 + + + storageProvider.datastoreUnmountRetryCount + 3 + + + storageProvider.datastoreUnmountRetryDelaySec + 1 + + + storageProvider.fixRecoveredDatastoreNames + false + + + storageProvider.fixRecoveredDatastoreNamesDelaySec + 0 + + + storageProvider.hostRescanDelaySec + 0 + + + storageProvider.hostRescanRepeatCnt + 1 + + + storageProvider.hostRescanTimeoutSec + 300 + + + storageProvider.resignatureFailureRetryCount + 1 + + + storageProvider.resignatureTimeoutSec + 900 + + + storageProvider.storageVmotionVmxFilePathsToSkip + .snapshot, + + + storageProvider.storageVmotionVmxSearch + true + + + storageProvider.stretchedDevicesMatchTimeout + 300 + + + storageProvider.vmMigrationLimitPerHost + 2 + + + storageProvider.waitForAccessibleDatastoreTimeoutSec + 60 + + + storageProvider.waitForDeviceRediscovery + false + + + storageProvider.waitForDeviceRediscoveryAfterPrepareFailover + false + + + storageProvider.waitForRecoveredDatastoreTimeoutSec + 30 + + + storageProvider.waitForVmfsVolumesMountedStateTimeoutSec + 30 + + + telemetry.proxyHost + + + + telemetry.proxyPort + 0 + + + telemetry.proxyUseSsl + false + + + vrReplication.allowOtherSolutionTagInRecovery + false + + + vrReplication.preserveMpitImagesAsSnapshots + true + + + vrReplication.reverseReplicationTimeout + 7200 + + + vrReplication.synchronizationTimeout + 7200 + + + vrReplication.timeDefault + 240 + + + + true + + connections.hmsPanicDelay + 5 + + + connections.hmsPingFailedDelay + 2 + + + connections.waitForUpdatesTimeout + 900 + + + exportHistory.numReports + 5 + + + localSiteStatus.checkInterval + 60 + + + localSiteStatus.eventFrequency + 600 + + + localSiteStatus.maxClockSkew + 20 + + + localSiteStatus.maxCpuUsage + 70 + + + localSiteStatus.minCertRemainingTime + 30 + + + localSiteStatus.minDiskSpace + 100 + + + localSiteStatus.minMemory + 32 + + + logManager.Default + verbose + + + logManager.ExternalAPI + verbose + + + logManager.HbrProvider + verbose + + + logManager.IPCustomizer + verbose + + + logManager.InventoryMapper + verbose + + + logManager.Licensing + verbose + + + logManager.Persistence + verbose + + + logManager.Recovery + verbose + + + logManager.RecoveryConfig + verbose + + + logManager.Replication + verbose + + + logManager.ServerAuthorization + verbose + + + logManager.SessionManager + verbose + + + logManager.SoapAdapter + info + + + logManager.Storage + verbose + + + logManager.StorageProvider + verbose + + + recovery.autoDeployGuestAlias + true + + + recovery.customizationShutdownTimeout + 300 + + + recovery.customizationTimeout + 600 + + + recovery.defaultPriority + 3 + + + recovery.forceRecovery + false + + + recovery.hostPowerOnTimeout + 1200 + + + recovery.powerOffTimeout + 300 + + + recovery.powerOnDelay + 0 + + + recovery.powerOnTimeout + 300 + + + recovery.skipGuestShutdown + false + + + recovery.useIpMapperAutomatically + true + + + remoteManager.defaultTimeout + 900 + + + remoteManager.enableCustomFields + true + + + remoteManager.powerOnAggregationInterval + 2000 + + + remoteManager.taskCancelDefaultTimeout + 300 + + + remoteManager.taskDefaultTimeout + 900 + + + remoteManager.taskProgressDefaultTimeout + 180 + + + remoteManager.xVcVMotionTimeout + 3600 + + + remoteSiteStatus.drPanicDelay + 5 + + + remoteSiteStatus.drPingFailedDelay + 2 + + + replication.disablePiggybackVmsCheckDuringDeactivate + false + + + replication.placeholderVmCreationTimeout + 300 + + + replication.pollForMissingInventoryMappings + false + + + replication.protectionInfoSyncTimeout + 900 + + + replication.protectionPollInterval + 120 + + + sso.sts.tokenLifetime + 28800 + + + storage.attachTagsDelaySec + 30 + + + storage.commandTimeout + 300 + + + storage.datastoreMonitoringPollingInterval + 30 + + + storage.enableSdrsStandardTagCategoryCreation + true + + + storage.enableSdrsTagging + true + + + storage.enableSdrsTaggingRepair + true + + + storage.maxConcurrentCommandCnt + 5 + + + storage.minDsGroupComputationInterval + 0 + + + storage.querySyncStatusPollingInterval + 30 + + + storage.sdrsTaggingPollInterval + 50 + + + storage.storagePingInterval + 86400 + + + storage.syncTimeout + 86400 + + + storagePolicyAbrReplication.policyDatastorePollInterval + 20 + + + storageProvider.autoDetachLUNsWithDuplicateVolume + true + + + storageProvider.autoResignatureMode + 0 + + + storageProvider.batchAttachTimeoutSec + 3600 + + + storageProvider.batchDetachTimeoutSec + 3600 + + + storageProvider.batchMountTimeoutSec + 3600 + + + storageProvider.batchUnmountTimeoutSec + 3600 + + + storageProvider.datastoreUnmountRetryCount + 3 + + + storageProvider.datastoreUnmountRetryDelaySec + 1 + + + storageProvider.fixRecoveredDatastoreNames + false + + + storageProvider.fixRecoveredDatastoreNamesDelaySec + 0 + + + storageProvider.hostRescanDelaySec + 0 + + + storageProvider.hostRescanRepeatCnt + 1 + + + storageProvider.hostRescanTimeoutSec + 300 + + + storageProvider.resignatureFailureRetryCount + 1 + + + storageProvider.resignatureTimeoutSec + 900 + + + storageProvider.storageVmotionVmxFilePathsToSkip + .snapshot, + + + storageProvider.storageVmotionVmxSearch + true + + + storageProvider.stretchedDevicesMatchTimeout + 300 + + + storageProvider.vmMigrationLimitPerHost + 2 + + + storageProvider.waitForAccessibleDatastoreTimeoutSec + 60 + + + storageProvider.waitForDeviceRediscovery + false + + + storageProvider.waitForDeviceRediscoveryAfterPrepareFailover + false + + + storageProvider.waitForRecoveredDatastoreTimeoutSec + 30 + + + storageProvider.waitForVmfsVolumesMountedStateTimeoutSec + 30 + + + telemetry.proxyHost + + + + telemetry.proxyPort + 0 + + + telemetry.proxyUseSsl + false + + + vrReplication.allowOtherSolutionTagInRecovery + false + + + vrReplication.preserveMpitImagesAsSnapshots + true + + + vrReplication.reverseReplicationTimeout + 7200 + + + vrReplication.synchronizationTimeout + 7200 + + + vrReplication.timeDefault + 240 + + + + + + + + l_vm_vm-1087 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1192 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1501 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1033 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1939 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1107 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1094 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1158 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-999 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3084 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1155 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3076 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2460 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1068 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1055 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1193 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1179 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2459 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2539 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1167 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1043 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1934 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1072 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1201 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1416 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1142 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1154 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1392 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1954 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1053 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1124 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1000 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1411 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1386 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1026 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3546 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1197 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1380 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-900 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1183 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1953 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1147 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1957 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1045 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2454 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1017 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1415 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2922 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2356 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2426 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-902 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2586 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1129 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1387 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1123 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-991 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1381 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1959 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1019 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1051 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1207 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1073 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1383 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1160 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1020 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1287 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1208 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1125 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2763 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1115 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1213 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1106 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2885 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1109 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1272 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1127 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1015 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1447 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2579 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2440 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1146 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1029 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1190 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1199 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3291 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1189 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1417 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1135 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-901 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2457 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1082 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1389 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1198 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1211 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1018 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-890 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1141 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1004 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1162 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1176 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1214 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1085 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1273 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-995 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1121 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1169 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1110 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1414 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2433 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-998 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1034 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-997 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1079 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1353 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1362 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1010 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1366 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1078 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1092 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1391 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1212 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1099 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1128 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1140 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2434 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1288 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1126 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1138 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1118 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-903 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1011 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1384 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1151 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2168 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1054 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1173 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1089 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1951 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1102 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3150 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1114 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2560 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1030 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1216 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1181 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1088 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1500 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1139 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1412 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1113 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1191 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1057 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1893 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2780 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1083 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1413 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1122 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1008 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1120 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1041 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2361 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2298 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1363 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1006 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1419 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1217 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2588 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1163 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-904 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1024 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1395 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-994 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2456 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2721 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1069 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1149 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1003 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2425 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1108 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1948 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1081 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1048 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1171 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2453 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1074 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1174 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1101 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2354 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1047 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1040 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1044 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3471 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-907 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3137 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1409 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1487 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1067 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1200 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1060 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1925 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1148 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1185 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1016 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1175 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1100 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1103 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1218 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1153 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1220 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1137 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1111 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1027 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-906 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1059 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1058 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1042 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1900 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1025 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2436 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1956 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2647 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-996 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1039 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1093 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1091 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2376 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1221 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1028 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1206 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1441 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1961 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1159 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2571 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1407 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1136 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2363 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2383 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1955 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1052 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2423 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1143 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2568 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1119 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1117 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2570 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1032 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2385 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2428 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1170 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2879 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1172 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3143 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1084 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1390 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1050 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1005 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2971 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1887 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1049 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1365 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2935 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1205 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2552 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1182 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3280 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2090 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1112 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1204 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1188 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1161 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1116 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1086 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1105 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3542 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1418 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1203 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1164 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1012 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1002 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1022 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3493 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3543 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1009 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1215 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1210 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2448 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1187 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1394 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1104 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1180 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1186 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1177 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1168 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1385 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1144 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-992 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1001 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1080 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1952 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1152 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1066 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1393 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2575 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1178 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35513 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14932 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25172 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25164 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34996 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14920 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-5405 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14945 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-48798 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-33084 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-5406 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14939 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25167 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-15849 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30912 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30907 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24862 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24857 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25168 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34207 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-49805 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45944 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-43967 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-16866 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14941 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14946 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-49803 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30640 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29906 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29308 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41444 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-36385 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29088 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-11739 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12915 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-36793 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-19963 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-28218 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-9148 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-7637 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30908 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44704 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-43282 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12305 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-9106 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14935 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24858 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-48381 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-26890 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25882 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-8177 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29089 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-20841 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-48924 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14921 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44702 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-39095 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25166 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14940 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-26891 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14473 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14936 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22729 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14948 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14472 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-16867 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29744 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24856 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-8173 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14471 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29086 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22733 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-13550 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-18822 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12916 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-18226 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25170 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45752 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44700 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44701 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-27452 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35515 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35518 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-11242 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30639 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25506 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29742 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44699 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29085 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22731 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-33988 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-18227 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35517 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45739 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44703 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14474 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-27545 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29087 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-9149 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14944 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-49804 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-49801 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29526 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-27453 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-31184 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-48797 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-8178 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45725 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30909 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44841 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12921 + 75 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45630 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24198 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-6087 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30910 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24864 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25169 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12730 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34611 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-37262 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41449 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-15366 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34995 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-43283 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-30911 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-28217 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14942 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45737 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-10173 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25173 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24861 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-27928 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41618 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-5664 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45736 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45741 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29743 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35516 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12304 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25412 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-29908 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22732 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22734 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-49802 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-39097 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14566 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25165 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35630 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-18126 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-12393 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-40139 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14943 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45724 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24860 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-35514 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45721 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45722 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-9428 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34997 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-45723 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-19436 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-25171 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-40140 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24863 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-34044 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-18228 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-22730 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-44705 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-24859 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-14947 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-9150 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3776 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-51789 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3777 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2353 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1958 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3366 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2532 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2587 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3411 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3155 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1927 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1928 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41450 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1410 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2938 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2462 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1379 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1926 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2529 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1935 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2377 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2347 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3223 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3057 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3539 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2809 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1281 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1878 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1429 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2381 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2561 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1936 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1924 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2572 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3499 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1882 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2592 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2435 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1430 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2382 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2718 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1950 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2835 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1947 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2088 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1420 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1382 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2760 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2958 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3142 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1883 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2445 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1874 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3215 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2378 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3021 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1350 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3230 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3557 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2458 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1876 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2961 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2815 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1891 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1884 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2355 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1388 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2421 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2976 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3295 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2351 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3483 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1949 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1877 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3550 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1929 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2825 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1875 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3224 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2562 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3560 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2437 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1863 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3158 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2089 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3537 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3372 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1879 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3544 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3089 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3413 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3387 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2836 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1885 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2359 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1864 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1421 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1422 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3020 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3369 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3553 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1868 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2583 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3540 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1873 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2469 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1351 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3549 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2880 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3009 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1871 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1945 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2465 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2367 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1881 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2422 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3234 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1425 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1890 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1352 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3025 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2566 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3555 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1866 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2461 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2591 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1931 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1872 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3375 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2358 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1870 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1869 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1424 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2722 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3502 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3548 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1322 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1880 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1938 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3285 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3074 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1865 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2449 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1423 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1886 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3154 + 60 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3202 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3541 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1867 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1321 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2590 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2364 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1428 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3558 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2813 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2429 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3552 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2297 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2350 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2601 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2472 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2926 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2773 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3551 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2582 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2384 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2569 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2366 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2431 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2470 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-3217 + 40 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-2430 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1960 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-1892 + 25 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41453 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + l_vm_vm-41345 + 50 + false + 300 + 300 + 0 + 600 + false + poweredOn + false + + + + + + + false + + r_folder_group-d1 + + r_dc_datacenter-2 + Secondary Datacenter + + r_folder_group-v3 + vm + + r_vm_vm-31652 + Red Hat Enterprise Linux 7 - Master Template + + + r_vm_vm-31653 + Windows 10 Enterprise LTSC 2019 + + + r_folder_group-v23907 + _Discovered Virtual Machines + + + r_folder_group-v15547 + DOA + + r_folder_group-v15721 + DOA-BeeMapping + + r_vm_vm-1749 + itdnddabeemapp1.nd.gov + + + + + r_folder_group-v15544 + RRI + + + r_folder_group-v15539 + DES + + r_folder_group-v14548 + DES-WebEOC + + r_vm_vm-2592 + itddesnett1.nd.gov + + + r_vm_vm-23073 + itddesnetp1.nd.gov + + + + + r_folder_group-v15551 + DMR + + + r_folder_group-v15538 + COM + + + r_folder_group-v6901 + _Migrated to Azure + + r_vm_vm-2508 + itddohimst1.nd.gov + + + r_vm_vm-2386 + itddpisaart1.nd.gov + + + r_vm_vm-2040 + itddpisaart2.nd.gov + + + + r_folder_group-v15521 + BND + + r_folder_group-v14185 + BND-WebSphere + + r_vm_vm-1224 + bnd0329.bnd.nd.gov + + + r_vm_vm-23233 + bnd0326.bnd.nd.gov + + + r_vm_vm-23234 + bnd0327.bnd.nd.gov + + + r_vm_vm-1218 + bnd0331.bnd.nd.gov + + + r_vm_vm-1227 + bnd0330.bnd.nd.gov + + + r_vm_vm-23232 + bnd0328.bnd.nd.gov + + + + r_folder_group-v15730 + BND-Sendero + + r_vm_vm-21824 + bnd1032.nd.gov + + + + r_folder_group-v24569 + BND-APCheck + + r_vm_vm-24566 + bnd1209.nd.gov + + + + r_folder_group-v118 + BND-Fiserv + + r_vm_vm-28448 + bnd1216.nd.gov + + + r_vm_vm-28445 + bnd0490.nd.gov + + + r_vm_vm-28444 + bnd0486.nd.gov + + + r_vm_vm-28446 + bnd1220.nd.gov + + + r_vm_vm-25550 + bnd1221.nd.gov + + + r_vm_vm-25549 + bnd1217.nd.gov + + + + r_folder_group-v117 + BND-FIS + + r_vm_vm-22967 + bnd0529.nd.gov + + + r_vm_vm-22977 + bnd0533.nd.gov + + + r_vm_vm-22974 + bnd0856.nd.gov + + + r_vm_vm-22971 + bnd0526.nd.gov + + + r_vm_vm-22970 + bnd0527.nd.gov + + + r_vm_vm-22975 + bnd0532.nd.gov + + + r_vm_vm-22969 + bnd0528.nd.gov + + + r_vm_vm-22968 + bnd0535.nd.gov + + + r_vm_vm-22976 + bnd0873.nd.gov + + + r_vm_vm-22965 + bnd0536.nd.gov + + + r_vm_vm-22973 + bnd0857.nd.gov + + + r_vm_vm-22972 + bnd0530.nd.gov + + + r_vm_vm-22966 + bnd0531.nd.gov + + + + r_folder_group-v14547 + BND-HELMS + + r_vm_vm-22989 + bnd0432.bnd.nd.gov + + + r_vm_vm-22987 + bnd0431.bnd.nd.gov + + + r_vm_vm-22986 + bnd0433.bnd.nd.gov + + + r_vm_vm-22988 + bnd0555.nd.gov + + + r_vm_vm-22990 + bnd0430.bnd.nd.gov + + + + r_folder_group-v14724 + BND-PitneyBowes + + r_vm_vm-25673 + bnd1218.nd.gov + + + r_vm_vm-2493 + itdbndpbtest.bnd.nd.gov + + + r_vm_vm-22996 + itdbndpbprod.bnd.nd.gov + + + + r_folder_group-v121 + BND-MFT + + r_vm_vm-23230 + bnd0600.nd.gov + + + r_vm_vm-2434 + bnd0599.nd.gov + + + r_vm_vm-23228 + bnd0603.nd.gov + + + r_vm_vm-2446 + bnd0598.nd.gov + + + r_vm_vm-23229 + bnd0601.nd.gov + + + r_vm_vm-2069 + bnd0596.nd.gov + + + r_vm_vm-23231 + bnd0602.nd.gov + + + r_vm_vm-2593 + bnd0597.nd.gov + + + + r_folder_group-v122 + BND-FUNDTECH + + r_vm_vm-22984 + bnd0424.bnd.nd.gov + + + r_vm_vm-22983 + bnd0656.nd.gov + + + r_vm_vm-22985 + bnd0824.nd.gov + + + r_vm_vm-22982 + bnd0425.bnd.nd.gov + + + + r_folder_group-v14700 + BND-SQL + + r_vm_vm-23006 + bnd0297.nd.gov + + + + r_folder_group-v14546 + BND-BondBanking + + r_vm_vm-22963 + bnd0556.nd.gov + + + + r_folder_group-v14698 + BND-MFA + + r_vm_vm-22993 + bnd0887.nd.gov + + + + r_folder_group-v14697 + BND-Jreport + + r_vm_vm-22991 + bnd0969.nd.gov + + + + r_folder_group-v14699 + BND-Shared-App + + r_vm_vm-24288 + bnd1208.nd.gov + + + r_vm_vm-23002 + bnd0703.nd.gov + + + r_vm_vm-23001 + bnd0224.bnd.nd.gov + + + + r_folder_group-v14545 + BND-Calyx + + r_vm_vm-22964 + bndapp12.bnd.nd.gov + + + + + r_folder_group-v22206 + DEQ + + r_folder_group-v22208 + DEQ-Web-Portal-Data + + r_vm_vm-19621 + itddeqnett1.nd.gov + + + + r_folder_group-v22207 + DEQ-Waste-Transporter + + r_vm_vm-21725 + itddeqappt1.nd.gov + + + + + r_folder_group-v15531 + OAH + + + r_folder_group-v15524 + DOH + + r_folder_group-v14782 + DOH-Shared-App + + r_vm_vm-23074 + itddohnetp3.nd.gov + + + r_vm_vm-2199 + itddohnett3.nd.gov + + + + r_folder_group-v15715 + DOH-WIC + + r_vm_vm-21640 + itddohlegendt3.nd.gov + + + r_vm_vm-2101 + itddohlegendt2.nd.gov + + + + r_folder_group-v14783 + DOH-USAFoodSafety + + r_vm_vm-23114 + itddohimsp1.nd.gov + + + + r_folder_group-v130 + DOH-PRS + + r_vm_vm-2474 + itddohnett4.nd.gov + + + r_vm_vm-23265 + itddohprsp1.nd.gov + + + r_folder_group-v147 + SRM Suspend + + + + + r_folder_group-v15523 + DOC + + + r_folder_group-v15550 + RIO + + + r_folder_group-v15522 + DHS + + r_folder_group-v14195 + DHS-MagiCloud + + r_vm_vm-23239 + itdrails.nd.gov + + + + r_folder_group-v15386 + DHS-MMIS-EDIFECS + + r_vm_vm-23087 + itdeditompxyp1.nd.gov + + + r_vm_vm-16222 + itdediretls3u1.nd.gov + + + r_vm_vm-16232 + itdeditompxyt1.nd.gov + + + r_vm_vm-23080 + itdedixecamqp1.nd.gov + + + r_vm_vm-16218 + itdedixesrtu1.nd.gov + + + r_vm_vm-16228 + itdedixesrtt1.nd.gov + + + r_vm_vm-16224 + itdediorels1u1.nd.gov + + + r_vm_vm-23079 + itdediretls3p1.nd.gov + + + r_vm_vm-23085 + itdeditompxyp2.nd.gov + + + r_vm_vm-16219 + itdedixesrtu2.nd.gov + + + r_vm_vm-16230 + itdediretls3t1.nd.gov + + + r_vm_vm-23081 + itddhsedifsp1.nd.gov + + + r_vm_vm-16229 + itdedibetls2st1.nd.gov + + + r_vm_vm-23086 + itdedixesrtp1.nd.gov + + + r_vm_vm-23084 + itdedixexesbp1.nd.gov + + + r_vm_vm-16227 + itdedixexesbt1.nd.gov + + + r_vm_vm-16221 + itdedibetls2su1.nd.gov + + + r_vm_vm-16231 + itdediorels1t1.nd.gov + + + r_vm_vm-16220 + itdedixecamqu1.nd.gov + + + r_vm_vm-16223 + itdediappwsu1.nd.gov + + + r_vm_vm-23077 + itdedixesrtp2.nd.gov + + + r_vm_vm-16217 + itdedixexesbu1.nd.gov + + + r_vm_vm-12826 + itdedixecamqt1.nd.gov + + + r_vm_vm-23083 + itdedibetls2sp1.nd.gov + + + r_vm_vm-16226 + itdeditompxyut2.nd.gov + + + r_vm_vm-23082 + itdediappwsp1.nd.gov + + + r_vm_vm-23078 + itdediorels1p1.nd.gov + + + r_vm_vm-16225 + itdeditompxyut1.nd.gov + + + + r_folder_group-v14197 + DHS-MMIS-LoadBalancer + + r_vm_vm-23089 + itdmmisldprod.mmis.nd.gov + + + r_vm_vm-1745 + itdmmisldtest.mmis.nd.gov + + + r_vm_vm-23088 + itdmmisextld1.nd.gov + + + + r_folder_group-v15385 + DHS-MMIS-Truven-Linux + + r_vm_vm-23112 + itdtrvcog.mmis.nd.gov + + + r_vm_vm-23111 + itdtrvsrv.mmis.nd.gov + + + r_vm_vm-23103 + itdtrvme.mmis.nd.gov + + + r_vm_vm-23106 + itdtrvgw.mmis.nd.gov + + + r_vm_vm-23110 + itdtrvpdb.mmis.nd.gov + + + r_vm_vm-23105 + itdtrvctm.mmis.nd.gov + + + + r_folder_group-v15384 + DHS-SPACES + + r_vm_vm-23062 + itddhsprdwasw04.nd.gov + + + r_vm_vm-23044 + itddhsprdsama01.nd.gov + + + r_vm_vm-23065 + itddhsprdwasa04.nd.gov + + + r_vm_vm-23064 + itddhsprdisea01.nd.gov + + + r_vm_vm-23066 + itddhsprdsdsd01.nd.gov + + + r_vm_vm-23042 + itddhsprdwasw02.nd.gov + + + r_vm_vm-23058 + itddhsprdrpta01.nd.gov + + + r_vm_vm-2083 + itddhshploadrun1.nd.gov + + + r_vm_vm-23049 + itddhsprdwasa05.nd.gov + + + r_vm_vm-23056 + itddhsprdwasa02.nd.gov + + + r_vm_vm-23047 + itddhsprdodma01.nd.gov + + + r_vm_vm-23052 + itddhsprdrptw02.nd.gov + + + r_vm_vm-23046 + itddhsprdbata01.nd.gov + + + r_vm_vm-23043 + itddhsprdrpta02.nd.gov + + + r_vm_vm-23061 + itddhsprdccma02.nd.gov + + + r_vm_vm-23048 + itddhsprdsima02.nd.gov + + + r_vm_vm-23060 + itddhsprdsdsd02.nd.gov + + + r_vm_vm-23050 + itddhsprdodma02.nd.gov + + + r_vm_vm-23059 + itddhsprdwasa03.nd.gov + + + r_vm_vm-23057 + itddhsprdbata02.nd.gov + + + r_vm_vm-23051 + itddhsprdsima01.nd.gov + + + r_vm_vm-23068 + itddhsprdsama02.nd.gov + + + r_vm_vm-23054 + itddhsprdrptw01.nd.gov + + + r_vm_vm-23053 + itddhshpxtrmlic.nd.gov + + + r_vm_vm-24995 + itdmdmeligsit1.nd.gov + + + r_vm_vm-23039 + itddhsprdccma01.nd.gov + + + r_vm_vm-23067 + itddhsprdwasw03.nd.gov + + + r_vm_vm-23055 + itddhsprdesba01.nd.gov + + + r_vm_vm-23040 + itddhsprdissa01.nd.gov + + + r_vm_vm-23045 + itddhsprdwasw01.nd.gov + + + r_vm_vm-23038 + itddhsprdwasa06.nd.gov + + + r_vm_vm-23063 + itddhsprdissm01.nd.gov + + + r_vm_vm-23069 + itddhsprdwasa01.nd.gov + + + r_vm_vm-23041 + itddhsprdesba02.nd.gov + + + r_vm_vm-2503 + itddhsvugen1.nd.gov + + + + r_folder_group-v24323 + DHS-MirrorImage + + r_vm_vm-24287 + itddhsmirrimgt1.nd.gov + + + r_vm_vm-24531 + itddhsmirrimgp1.nd.gov + + + + r_folder_group-v14550 + DHS-CDC + + r_vm_vm-1748 + itdcdctest.nd.gov + + + r_vm_vm-26925 + itdcdctest2.nd.gov + + + r_vm_vm-23237 + itdcdcprod.nd.gov + + + r_vm_vm-27098 + itdcdcprod2.nd.gov + + + + r_folder_group-v14849 + DHS-VISION + + r_vm_vm-23249 + itddlmprtprod.nd.gov + + + r_vm_vm-23251 + itdvisioncomp1.nd.gov + + + r_vm_vm-23250 + itdblazep1.nd.gov + + + r_vm_vm-28244 + itdcagenadmin.nd.gov + + + r_vm_vm-23247 + itdcse3.nd.gov + + + r_vm_vm-23248 + itdvisioncomp2.nd.gov + + + + r_folder_group-v14752 + DHS-MMIS-COGNOS + + r_vm_vm-23075 + itdcogmmisprm.prm.mmis.nd.gov + + + r_vm_vm-23076 + itdcogmmisprm2.prm.mmis.nd.gov + + + + r_folder_group-v14555 + DHS-SPACES-EDMS + + r_vm_vm-2202 + itdfncn4tst.nd.gov + + + r_vm_vm-23607 + itdfncn4.nd.gov + + + + r_folder_group-v14850 + DHS-Workforce-Windows + + r_vm_vm-23263 + itddhswfrcp1.nd.gov + + + r_vm_vm-23262 + itddhswfrcrptp1.nd.gov + + + + r_folder_group-v15736 + DHS-MMIS-Xpressions-SQL + + r_vm_vm-23182 + itdprmxprsql1.mmis.nd.gov + + + + r_folder_group-v14735 + DHS-AWARE + + + r_folder_group-v14848 + DHS-PitneyBowes + + r_vm_vm-23940 + itddhspbows1.nd.gov + + + r_vm_vm-23240 + itdpbows1.nd.gov + + + + r_folder_group-v14766 + DHS-MMIS-MoveIt + + r_vm_vm-2441 + itddhsmidmzt1.mmis.nd.gov + + + r_vm_vm-23091 + itddhsmidmzp1.mmis.nd.gov + + + r_vm_vm-23090 + itddhsmicenp1.mmis.nd.gov + + + r_vm_vm-2064 + itddhsmicent1.mmis.nd.gov + + + + r_folder_group-v14739 + DHS-OpenScan + + r_vm_vm-2587 + itdopenscan1tst.itd.nd.gov + + + r_vm_vm-23117 + itdopenscan1.itd.nd.gov + + + + r_folder_group-v14551 + DHS-Mediclaim + + r_vm_vm-23176 + itdtfdhss2.nd.gov + + + r_vm_vm-23177 + itdtfdhsr2.nd.gov + + + r_vm_vm-2058 + itdtfdhs2tst.nd.gov + + + + r_folder_group-v14767 + DHS-MMIS-Xpressions + + r_vm_vm-2038 + itduatxpr4.mmis.nd.gov + + + r_vm_vm-2232 + itdsitxpr4.mmis.nd.gov + + + r_vm_vm-23115 + itdprmxpr4.mmis.nd.gov + + + + r_folder_group-v16479 + DHS-MMIS-SIM-SAM + + r_vm_vm-17208 + itduattim2a.nd.gov + + + r_vm_vm-23092 + itdprmtam2a.nd.gov + + + r_vm_vm-23100 + itdprmtam1a.nd.gov + + + r_vm_vm-17177 + itdtrmtam1a.nd.gov + + + r_vm_vm-23098 + itdprmldap1a.nd.gov + + + r_vm_vm-17180 + itdsittam1a.nd.gov + + + r_vm_vm-17205 + itduatldap1a.nd.gov + + + r_vm_vm-17206 + itduatldap2a.nd.gov + + + r_vm_vm-23095 + itdprmtam3a.nd.gov + + + r_vm_vm-17178 + itdtrmtim1a.nd.gov + + + r_vm_vm-17392 + itduattam1a.nd.gov + + + r_vm_vm-23097 + itdprmldap3a.nd.gov + + + r_vm_vm-23096 + itdprmtim3a.nd.gov + + + r_vm_vm-23099 + itdprmtim2a.nd.gov + + + r_vm_vm-23093 + itdprmldap2a.nd.gov + + + r_vm_vm-17207 + itduattim1a.nd.gov + + + r_vm_vm-17150 + itdsittim1a.nd.gov + + + r_vm_vm-23094 + itdprmtim1a.nd.gov + + + r_vm_vm-17179 + itdsitldap1a.nd.gov + + + r_vm_vm-17176 + itdtrmldap1a.nd.gov + + + r_vm_vm-17393 + itduattam2a.nd.gov + + + + r_folder_group-v14740 + DHS-Orchard + + r_vm_vm-31605 + itddhshvsthl7t1.nd.gov + + + r_vm_vm-23070 + itddhsharvestw.nd.gov + + + r_vm_vm-23072 + itddhshvsthl7.nd.gov + + + r_vm_vm-23071 + itddhsharvest.nd.gov + + + + r_folder_group-v15700 + DHS-Pyxis + + r_vm_vm-10905 + itddhspyxmest1.nd.gov + + + r_vm_vm-9104 + itddhspyxccet1.nd.gov + + + r_vm_vm-26600 + itddhspyxccep1.nd.gov + + + r_vm_vm-26599 + itddhspyxesp1.nd.gov + + + r_vm_vm-9105 + itddhspyxest1.nd.gov + + + + r_folder_group-v15737 + DHS-SPACES-F5 + + r_vm_vm-23183 + itdbdcf5vp1.nd.gov + + + + r_folder_group-v15732 + DHS-COMPUTRITION + + r_vm_vm-1905 + itddhscompifxt1.nd.gov + + + r_vm_vm-21412 + itddhscompifxt.nd.gov + + + + r_folder_group-v15705 + DHS-MMIS-ActiveDirectory + + r_vm_vm-2198 + itdtrndc1.trn.mmis.dev + + + r_vm_vm-2358 + itdsitdc1.sit.mmis.dev + + + r_vm_vm-2443 + itdtstdc1.tst.mmis.dev + + + r_vm_vm-2418 + itduatdc2.uat.mmis.dev + + + r_vm_vm-2216 + itduatdc1.uat.mmis.dev + + + + r_folder_group-v14188 + DHS-WebSphere + + r_vm_vm-23256 + itdws8p6a.nd.gov + + + r_vm_vm-1215 + itdintws9t6.nd.gov + + + r_vm_vm-1233 + itdws9t6.nd.gov + + + r_vm_vm-23259 + itdintws9p5.nd.gov + + + r_vm_vm-23258 + itdintws9p6.nd.gov + + + r_vm_vm-23254 + itdintws8p5a.nd.gov + + + r_vm_vm-23261 + itdintws8p6a.nd.gov + + + r_vm_vm-23260 + itdws9p5.nd.gov + + + r_vm_vm-1189 + itdintws9t5.nd.gov + + + r_vm_vm-23257 + itdws8p5a.nd.gov + + + r_vm_vm-1284 + itdintws8t5a.nd.gov + + + r_vm_vm-1234 + itdws8t6a.nd.gov + + + r_vm_vm-1255 + itdws9t5.nd.gov + + + r_vm_vm-23255 + itdws9p6.nd.gov + + + r_vm_vm-1282 + itdintws8t6a.nd.gov + + + r_vm_vm-1217 + itdws8t5a.nd.gov + + + + r_folder_group-v14556 + DHS-QMS + + r_vm_vm-23246 + itddhsqmsp1.nd.gov + + + + r_folder_group-v14768 + DHS-MMIS-UC4 + + r_vm_vm-23113 + itddhsuc4p1.mmis.nd.gov + + + r_vm_vm-30516 + itddhsuc4t2.nd.gov + + + r_vm_vm-31071 + itddhsuc4p2.nd.gov + + + + + r_folder_group-v80 + _Delete Request + + r_vm_vm-2240 + itdskypeman2.nd.gov-DLDelete20200624 + + + r_vm_vm-2213 + itdskypeman1.nd.gov-DLDelete20200624 + + + r_vm_vm-18479 + itdmdmdevl1.nd.gov-DLDelete20200624 + + + + r_folder_group-v15542 + HPN + + r_folder_group-v25367 + HPN-ProMiles + + r_vm_vm-25366 + itdhpneart2.nd.gov + + + + + r_folder_group-v15534 + TAX + + r_folder_group-v143 + TAX-GenTax + + r_vm_vm-1295 + itdtaxsql16p2.nd.gov + + + r_vm_vm-28982 + itdtaxpta1.nd.gov + + + r_vm_vm-28983 + itdtaxpga1.nd.gov + + + r_vm_vm-22619 + itdtaxsga1.nd.gov + + + r_vm_vm-22616 + itdtaxsta1.nd.gov + + + r_vm_vm-22617 + itdtaxstw1.nd.gov + + + r_vm_vm-23196 + itdtaxpfa1.nd.gov + + + r_vm_vm-22618 + itdtaxtga1.nd.gov + + + r_vm_vm-22620 + itdtaxsga2.nd.gov + + + r_vm_vm-25118 + itdtaxsql19dts1.nd.gov + + + r_vm_vm-28985 + itdtaxptw1.nd.gov + + + r_vm_vm-25148 + itdtaxsql19p2.nd.gov + + + r_vm_vm-28986 + itdtaxpga2.nd.gov + + + + + r_folder_group-v79 + _Clone Request + + r_vm_vm-32182 + itdscmt1.nd.gov_AutoClone_155 + + + r_vm_vm-27750 + itdfncc4tst.nd.gov_AutoClone_2162 + + + + r_folder_group-v15540 + DPI + + r_folder_group-v132 + DPI-SAAR + + r_vm_vm-30881 + itddpisaart3.nd.gov + + + r_vm_vm-23274 + itddpisaarp1.nd.gov + + + r_vm_vm-30882 + itddpisaart4.nd.gov + + + r_vm_vm-31070 + itddpisaarp3.nd.gov + + + r_vm_vm-23273 + itddpisaarp2.nd.gov + + + r_vm_vm-31072 + itddpisaarp4.nd.gov + + + + r_folder_group-v15549 + PSC + + + r_folder_group-v27868 + DPI-Shared-IIS + + r_vm_vm-27800 + itddpinett1.nd.gov + + + + + r_folder_group-v15532 + OMB + + r_folder_group-v15708 + OMB-IBARS + + r_vm_vm-1901 + itdombibarst1.nd.gov + + + r_vm_vm-1927 + itdombibarst2.nd.gov + + + + + r_folder_group-v26823 + Discovered virtual machine + + + r_folder_group-v15533 + SOS + + r_folder_group-v5862 + SOS-BLS + + r_vm_vm-23201 + itdsosblswebp1.nd.gov + + + r_vm_vm-23202 + itdsosblsappp1.nd.gov + + + + r_folder_group-v26491 + SOS-BPRO + + r_vm_vm-26252 + itdsosvoicest2.nd.gov + + + + r_folder_group-v142 + SOS-CentralIndexing + + r_vm_vm-23005 + itdsoscisqlp1.nd.gov + + + r_vm_vm-2420 + itdsosindext1.nd.gov + + + r_vm_vm-2385 + itdsoscisqltrn1.nd.gov + + + r_vm_vm-23004 + itdsosindexp1.nd.gov + + + r_vm_vm-2384 + itdsoscisqlt1.nd.gov + + + r_vm_vm-2452 + itdsosindextrn1.nd.gov + + + r_vm_vm-23003 + itdsosindexp2.nd.gov + + + + + r_folder_group-v81 + _Templates + + r_vm_vm-10904 + Windows 10 Enterprise 64Bit LTSB 1607 + + + r_vm_vm-20444 + Windows Server 2012R2 Standard + + + r_vm_vm-16480 + Red Hat Enterprise Linux 6 - Master Template + + + r_vm_vm-1916 + Red Hat Enterprise Linux - Tomcat + + + r_vm_vm-26819 + Windows Server 2019 Standard + + + r_vm_vm-29700 + Windows Server 2016 Standard + + + r_vm_vm-2223 + Windows Server 2008R2 SP1 Datacenter + + + r_vm_vm-16215 + EDI Test 02-2019 + + + + r_folder_group-v15546 + WSI + + r_folder_group-v14180 + WSI-Reporting + + r_vm_vm-32215 + itdwsisqlsrxp1.nd.gov + + + r_vm_vm-1593 + itdwsisqlrepd1.nd.gov + + + r_vm_vm-17363 + itdwsisqlsrxt1.nd.gov + + + r_vm_vm-1572 + itdwsisqlsrst1.nd.gov + + + r_vm_vm-1294 + itdwsisqlsast1.nd.gov + + + r_vm_vm-23189 + itdwsisqlsrsp1.nd.gov + + + r_vm_vm-23188 + itdwsisqlsasp1.nd.gov + + + + r_folder_group-v15707 + WSI-Extranet-SQL + + r_vm_vm-1599 + itdwsiextsqld1.nd.gov + + + r_vm_vm-1458 + itdwsiextsqldr.nd.gov + + + r_vm_vm-1267 + itdwsiextsqlt1.nd.gov + + + + r_folder_group-v14701 + WSI-Extranet + + r_vm_vm-23193 + itdwsiextappp2.nd.gov + + + r_vm_vm-23192 + itdwsiextappp1.nd.gov + + + r_vm_vm-2512 + itdwsiextappt2.nd.gov + + + r_vm_vm-2383 + itdwsiextappt1.nd.gov + + + + r_folder_group-v14560 + WSI-CAPS + + r_vm_vm-23194 + itdwsiprdweb01.nd.gov + + + + r_folder_group-v14705 + WSI-PitneyBowes + + r_vm_vm-26606 + itdwsipb2.nd.gov + + + + r_folder_group-v14706 + WSI-Shared-App + + r_vm_vm-22992 + wsiapp1.itd.nd.gov + + + + r_folder_group-v14702 + WSI-Forms + + + r_folder_group-v14703 + WSI-ITSM + + r_vm_vm-22995 + itdwsiitsm.nd.gov + + + + r_folder_group-v14704 + WSI-Oracle-Reports + + r_vm_vm-22994 + wsireports.nd.gov + + + r_vm_vm-2362 + wsireportst1.itd.nd.gov + + + + + r_folder_group-v15529 + ITD + + r_folder_group-v15381 + ITD-Workforce + + r_vm_vm-23338 + itdwfrcp1.nd.gov + + + r_vm_vm-21038 + itdwfrcrptt2.nd.gov + + + r_vm_vm-23339 + itdwfrcrptp1.nd.gov + + + r_vm_vm-23337 + itdwfrcrptp2.nd.gov + + + r_vm_vm-8306 + itdwfrct1.nd.gov + + + + r_folder_group-v15722 + ITD-SLDS-LRS + + r_vm_vm-16351 + itdlrst1.nd.gov + + + + r_folder_group-v28925 + ITD-EDUTech-WordPress + + r_vm_vm-28730 + itdedunpdcms01.nd.gov + + + r_vm_vm-28731 + itdedunpdcms02.nd.gov + + + + r_folder_group-v17915 + ITD-POC-Linux + + r_vm_vm-18605 + itdnfspoc2.nd.gov + + + r_vm_vm-17914 + itdnfspoc.nd.gov + + + + r_folder_group-v28849 + ITD-POC-Tier2 + + r_vm_vm-28496 + itdscmt1.nd.gov + + + + r_folder_group-v20442 + ITD-SLDS + + r_vm_vm-20413 + itdsledsqltrnd.ndcloud.gov + + + + r_folder_group-v18143 + ITD-EDUTech-Apache + + r_vm_vm-18116 + itdedutechwebt1.nd.gov + + + + r_folder_group-v22710 + ITD-POC-BI + + r_vm_vm-22709 + itdcogdkrpoc1.nd.gov + + + + r_folder_group-v14933 + ITD-GIS-HUB + + r_vm_vm-23342 + itdgisfme4.nd.gov + + + r_vm_vm-23343 + itdgisags3.nd.gov + + + r_vm_vm-23341 + itdgisags1.nd.gov + + + + r_folder_group-v19362 + ITD-SLDS-dotNET + + r_vm_vm-19361 + itdcloudnett2.ndcloud.gov + + + + r_folder_group-v15706 + ITD-POC-Storage + + + r_folder_group-v21729 + ITD-POC-DBA + + r_vm_vm-21728 + itdsql19dbat1.nd.gov + + + + r_folder_group-v19711 + ITD-GIS-HUB-SQL + + r_vm_vm-19709 + itdsql17gisp1dr.nd.gov + + + + + r_folder_group-v15526 + ERN + + r_folder_group-v15097 + ERN-PERSLink-Mobile + + r_vm_vm-26822 + itdernmobt01.nd.gov + + + r_vm_vm-23287 + itdernsag12.nd.gov + + + r_vm_vm-23286 + itdernsag13.nd.gov + + + + r_folder_group-v14559 + ERN-PERSLink + + r_vm_vm-26821 + itdernappu01.nd.gov + + + r_vm_vm-23280 + itdernsag8.nd.gov + + + r_vm_vm-23282 + itdernsag5.nd.gov + + + r_vm_vm-23284 + itdernsag3.nd.gov + + + r_vm_vm-23281 + itdernsag6.nd.gov + + + r_vm_vm-26820 + itdernappt01.nd.gov + + + r_vm_vm-23283 + itdernsag4.nd.gov + + + r_vm_vm-2230 + itdernsag1.nd.gov + + + r_vm_vm-2091 + itdernsag2.nd.gov + + + + + r_folder_group-v15527 + HED + + + r_folder_group-v15541 + GNF + + r_folder_group-v14189 + GNF-WebSphere + + r_vm_vm-23290 + itdws9p7.nd.gov + + + r_vm_vm-6716 + itdws9t8.nd.gov + + + r_vm_vm-6715 + itdws9t7.nd.gov + + + r_vm_vm-23289 + itdws9p8.nd.gov + + + r_vm_vm-6717 + itdws9tf2.nd.gov + + + r_vm_vm-23291 + itdws9pf2.nd.gov + + + + + r_folder_group-v15528 + CJIS + + r_folder_group-v15717 + CJIS-LERMS-SQL + + r_vm_vm-23037 + itdpremiersqlp1.nd.gov + + + r_vm_vm-2566 + itdpremiersqlt2.nd.gov + + + r_vm_vm-23036 + itdpremiersqlr1.nd.gov + + + + r_folder_group-v15729 + CJIS-Justware-SQL + + r_vm_vm-7915 + itdcjissql16t1.nd.gov + + + + r_folder_group-v15702 + CJIS-WebSphere + + r_vm_vm-1750 + itdcjisws9tf1.nd.gov + + + r_vm_vm-1889 + itdcjisws9tf2.nd.gov + + + r_vm_vm-1182 + itdcjisws9t1.nd.gov + + + r_vm_vm-1181 + itdcjisws9t3.nd.gov + + + r_vm_vm-1254 + itdcjisws9t2.nd.gov + + + r_vm_vm-1179 + itdcjisws9t4.nd.gov + + + + r_folder_group-v133 + CJIS-LERMS + + r_vm_vm-23007 + itdpremierp1.nd.gov + + + r_vm_vm-2049 + itdpremiertrn1.nd.gov + + + + + r_folder_group-v25658 + _New Builds + + + r_folder_group-v15545 + SHS + + + r_folder_group-v15543 + JSN + + r_folder_group-v15723 + JSN-EOM + + r_vm_vm-22090 + itdjsneomt1.nd.gov + + + + r_folder_group-v24570 + JSN-IBIQ + + r_vm_vm-24567 + itdjsnibiqt1.nd.gov + + + + r_folder_group-v139 + JSN-UIAA + + r_vm_vm-23336 + itdjsnuip1.nd.gov + + + r_vm_vm-2437 + itdjsnuit1.nd.gov + + + r_vm_vm-28884 + itdjsnuit2.nd.gov + + + r_vm_vm-28927 + itdjsnrdsp1.nd.gov + + + + r_folder_group-v30854 + JSN-UIICE + + + + r_folder_group-v15530 + LCN + + r_folder_group-v15380 + LCN-LEGEND + + r_vm_vm-5176 + itdrdbmolegend.nd.gov + + + r_vm_vm-5175 + itdpubmolegend.nd.gov + + + r_vm_vm-23167 + itdapplegend.nd.gov + + + r_vm_vm-23170 + itdrdb.legend.nd.gov + + + r_vm_vm-23168 + itdrdblegend.nd.gov + + + r_vm_vm-5178 + itdpgmolegend.nd.gov + + + r_vm_vm-5179 + itdpubsitlegend.nd.gov + + + r_vm_vm-23171 + itdpublegend.nd.gov + + + r_vm_vm-5177 + itdappmolegend.nd.gov + + + r_vm_vm-23169 + itdpglegend.nd.gov + + + r_vm_vm-5182 + itdpgsitlegend.nd.gov + + + r_vm_vm-5181 + itdappsitlegend.nd.gov + + + r_vm_vm-5180 + itdrdbsitlegend.nd.gov + + + + r_folder_group-v15728 + LCN-LEGEND-RND + + r_vm_vm-2088 + itdrnd1a.mo.legend.nd.gov + + + r_vm_vm-28449 + itdrnd1a.legend.nd.gov + + + r_vm_vm-2427 + itdrnd2a.mo.legend.nd.gov + + + r_vm_vm-28450 + itdrnd2a.legend.nd.gov + + + + + r_folder_group-v15535 + Shared + + r_folder_group-v32179 + Shared-MariaDB + + r_vm_vm-30483 + itdmariadbt1.nd.gov + + + + r_folder_group-v14879 + Shared-EDMS-App + + r_vm_vm-23323 + itdedmsp1.nd.gov + + + + r_folder_group-v15378 + Shared-WebSphere + + r_vm_vm-1219 + itdws9t2.nd.gov + + + r_vm_vm-1191 + itdintws8t2a.nd.gov + + + r_vm_vm-1228 + itdintws9dmgrt1.nd.gov + + + r_vm_vm-23220 + itdws8p4a.nd.gov + + + r_vm_vm-1178 + itdintws9t4.nd.gov + + + r_vm_vm-1903 + itdintws8tf1.itd.nd.gov + + + r_vm_vm-23204 + itdintws9dmgrp1.nd.gov + + + r_vm_vm-1276 + itdws8t2a.nd.gov + + + r_vm_vm-23222 + itdintws8dmgrp1.nd.gov + + + r_vm_vm-1256 + itdintws8stg1.nd.gov + + + r_vm_vm-23218 + itdws8f1.itd.nd.gov + + + r_vm_vm-1231 + itdws9sit1.nd.gov + + + r_vm_vm-1921 + itdintws9tf1.nd.gov + + + r_vm_vm-23207 + itdintws8f1.itd.nd.gov + + + r_vm_vm-23221 + itdws8p3a.nd.gov + + + r_vm_vm-1180 + itdintws9t2.nd.gov + + + r_vm_vm-5807 + itdintws9trn1.nd.gov + + + r_vm_vm-1278 + itdws9t3.nd.gov + + + r_vm_vm-1226 + itdintws9sit1.nd.gov + + + r_vm_vm-1188 + itdintws8t3a.nd.gov + + + r_vm_vm-23219 + itdintws8p4a.nd.gov + + + r_vm_vm-1216 + itdws8t3a.nd.gov + + + r_vm_vm-1257 + itdws9dmgrt1.nd.gov + + + r_vm_vm-23224 + itdintws8p3a.nd.gov + + + r_vm_vm-5808 + itdintws9uat1.nd.gov + + + r_vm_vm-23206 + itdintws9p3.nd.gov + + + r_vm_vm-23214 + itdws9p4.nd.gov + + + r_vm_vm-1279 + itdintws9t3.nd.gov + + + r_vm_vm-5811 + itdws9uat1.nd.gov + + + r_vm_vm-23216 + itdintws9p4.nd.gov + + + r_vm_vm-1277 + itdintws8sit1.itd.nd.gov + + + r_vm_vm-5806 + itdintws9stg1.nd.gov + + + r_vm_vm-1235 + itdintws8uat1.nd.gov + + + r_vm_vm-1229 + itdws8dmgrt1.itd.nd.gov + + + r_vm_vm-1190 + itdintws9t1.nd.gov + + + r_vm_vm-1223 + itdintws8trn1.nd.gov + + + r_vm_vm-5809 + itdws9stg1.nd.gov + + + r_vm_vm-1281 + itdintws8sit3.itd.nd.gov + + + r_vm_vm-1890 + itdws8tf1.itd.nd.gov + + + r_vm_vm-23226 + itdintws8p1a.nd.gov + + + r_vm_vm-1186 + itdintws8t4a.nd.gov + + + r_vm_vm-1924 + itdws9tf1.nd.gov + + + r_vm_vm-23217 + itdws9p2.nd.gov + + + r_vm_vm-1184 + itdws8t4a.nd.gov + + + r_vm_vm-5810 + itdws9trn1.nd.gov + + + r_vm_vm-1187 + itdintws8t1a.nd.gov + + + r_vm_vm-1232 + itdintws8dmgrt1.nd.gov + + + r_vm_vm-1249 + itdws9t4.nd.gov + + + r_vm_vm-23210 + itdws9p3.nd.gov + + + r_vm_vm-23223 + itdws9dmgrp1.nd.gov + + + r_vm_vm-23208 + itdws9p1.nd.gov + + + r_vm_vm-23205 + itdws8p2a.nd.gov + + + r_vm_vm-23211 + itdintws9pf1.nd.gov + + + r_vm_vm-23215 + itdws8p1a.nd.gov + + + r_vm_vm-23225 + itdintws9p2.nd.gov + + + r_vm_vm-23209 + itdintws9p1.nd.gov + + + r_vm_vm-23212 + itdintws8p2a.nd.gov + + + r_vm_vm-26856 + itdws9pf1.nd.gov + + + r_vm_vm-1222 + itdws9t1.nd.gov + + + r_vm_vm-1221 + itdws8t1a.nd.gov + + + r_vm_vm-23213 + itdws8dmgrp1.nd.gov + + + + r_folder_group-v14190 + Shared-EDMS-Adobe + + r_vm_vm-1253 + itdaem1tst.nd.gov + + + r_vm_vm-1250 + itdaem1dev.nd.gov + + + r_vm_vm-23324 + itdaem1prd.nd.gov + + + + r_folder_group-v15124 + Shared-K12-ViewPoint + + + r_folder_group-v14881 + Shared-EDMS-iLINX + + r_vm_vm-2371 + itdilem1tst.nd.gov + + + r_vm_vm-2041 + itdilweb2tst.nd.gov + + + r_vm_vm-2224 + itdilapp1tst.nd.gov + + + r_vm_vm-23388 + itdilef1.nd.gov + + + r_vm_vm-2488 + itdilweb1tst.nd.gov + + + r_vm_vm-23303 + itdilweb1.nd.gov + + + r_vm_vm-23304 + itdilem1.nd.gov + + + r_vm_vm-23305 + itdilapp1.nd.gov + + + r_vm_vm-8278 + itdilef1tst.nd.gov + + + r_vm_vm-23302 + itdilweb2.nd.gov + + + + r_folder_group-v14852 + Shared-SystemZ + + r_vm_vm-23264 + itdrpm1.nd.gov + + + + r_folder_group-v14730 + Shared-dotNet + + r_vm_vm-17661 + itdnett4.nd.gov + + + r_vm_vm-23175 + itdnetp1.itd.nd.gov + + + r_vm_vm-23328 + itdnet35p1.itd.nd.gov + + + + r_folder_group-v18144 + Shared-PowerBI + + r_vm_vm-18117 + itdpbidgt1.nd.gov + + + + r_folder_group-v28498 + Shared-ServiceNow + + r_vm_vm-28499 + itdesmmid1.nd.gov + + + + r_folder_group-v14851 + Shared-LotusDomino + + r_vm_vm-23277 + dhssosrvlnhub.itd.nd.gov + + + r_vm_vm-26887 + dhssosrvlnapp.itd.nd.gov + + + r_vm_vm-23278 + nodak02.itd.nd.gov + + + + r_folder_group-v134 + Shared-PeopleSoft-State + + r_vm_vm-31200 + itdcndstrt16.nd.gov + + + r_vm_vm-31199 + itdcndstrd16.nd.gov + + + r_vm_vm-31196 + itdcndstlt16.nd.gov + + + r_vm_vm-31195 + itdcndstld16.nd.gov + + + r_vm_vm-31197 + itdcndsthd16.nd.gov + + + r_vm_vm-29706 + itdcndsrvm.nd.gov + + + r_vm_vm-29704 + itdcndslvm.nd.gov + + + r_vm_vm-29705 + itdcndsfvm.nd.gov + + + r_vm_vm-31708 + itdcndh16es04.nd.gov + + + r_vm_vm-31198 + itdcndstht16.nd.gov + + + r_vm_vm-28935 + itdcndsf16app1.nd.gov + + + r_vm_vm-25660 + itdcndspmdb16.nd.gov + + + r_vm_vm-28934 + itdcndsf16sowp.nd.gov + + + r_vm_vm-26103 + itdcndstfd16.nd.gov + + + r_vm_vm-2577 + itdcndstrwt6.nd.gov + + + r_vm_vm-2426 + itdcndsthd.nd.gov + + + r_vm_vm-15495 + itdcndsftdb16.nd.gov + + + r_vm_vm-16038 + itdcndstrqwt2.nd.gov + + + r_vm_vm-26583 + itdcndstphire.nd.gov + + + r_vm_vm-2557 + itdcndsthqapp2.nd.gov + + + r_vm_vm-26577 + itdcndsturdp1.nd.gov + + + r_vm_vm-28885 + itdcndstro08.nd.gov + + + r_vm_vm-2226 + itdcndstthrs.nd.gov + + + r_vm_vm-2364 + itdcndsttrrs.nd.gov + + + r_vm_vm-28931 + itdcndsf16app2.nd.gov + + + r_vm_vm-28895 + itdcndstfwt8.nd.gov + + + r_vm_vm-28976 + itdcndstrrdp8.nd.gov + + + r_vm_vm-26104 + itdcndstft16.nd.gov + + + r_vm_vm-16039 + itdcndsthqwt1.nd.gov + + + r_vm_vm-2431 + itdcndstlo06.nd.gov + + + r_vm_vm-31065 + itdcnds16es02.nd.gov + + + r_vm_vm-28892 + itdcndsthwt8.nd.gov + + + r_vm_vm-2430 + itdcndstlwt6.nd.gov + + + r_vm_vm-26098 + itdcndsf16qapp2.nd.gov + + + r_vm_vm-28893 + itdcndstfo08.nd.gov + + + r_vm_vm-26566 + itdcndsthwp1.nd.gov + + + r_vm_vm-16037 + itdcndstrqwt1.nd.gov + + + r_vm_vm-26582 + itdcndsthcgwp.nd.gov + + + r_vm_vm-2044 + itdcndsthqwt.nd.gov + + + r_vm_vm-26560 + itdcndsthwp.nd.gov + + + r_vm_vm-28890 + itdcndstho08.nd.gov + + + r_vm_vm-21526 + itdcndstlqapp2.nd.gov + + + r_vm_vm-28850 + itdcndsf16ywt.nd.gov + + + r_vm_vm-28933 + itdcndsf16wp1.nd.gov + + + r_vm_vm-2439 + itdcndsthqapp1.nd.gov + + + r_vm_vm-26594 + itdcndstfrdp6.nd.gov + + + r_vm_vm-26588 + itdcndstbooks1.nd.gov + + + r_vm_vm-25664 + itdcndspmapp16.nd.gov + + + r_vm_vm-26592 + itdcndstgateway.nd.gov + + + r_vm_vm-28889 + itdcndstlwt8.nd.gov + + + r_vm_vm-4989 + itdcndsthcgwt1.nd.gov + + + r_vm_vm-26063 + itdcndslpdb16dr.nd.gov + + + r_vm_vm-32039 + itdcndstfc16.nd.gov + + + r_vm_vm-16040 + itdcndsthqwt2.nd.gov + + + r_vm_vm-2388 + itdcndstrqps.nd.gov + + + r_vm_vm-2447 + itdcndstlqps.nd.gov + + + r_vm_vm-26064 + itdcndshpdb16dr.nd.gov + + + r_vm_vm-28929 + itdcndsf16ps.nd.gov + + + r_vm_vm-26134 + itdcndsf16wt6.nd.gov + + + r_vm_vm-27801 + itdcndstfo0616.nd.gov + + + r_vm_vm-31064 + itdcnds16es03.nd.gov + + + r_vm_vm-31069 + itdcndsh16app2.nd.gov + + + r_vm_vm-31067 + itdcndsh16ps.nd.gov + + + r_vm_vm-27799 + itdcndstfy16.nd.gov + + + r_vm_vm-2100 + itdcndstlqapp1.nd.gov + + + r_vm_vm-2051 + itdcndstro06.nd.gov + + + r_vm_vm-2475 + itdcndstfwt3.nd.gov + + + r_vm_vm-26591 + itdcndstlwp1.nd.gov + + + r_vm_vm-28977 + itdcndstlrdp8.nd.gov + + + r_vm_vm-26099 + itdcndsf16qps.nd.gov + + + r_vm_vm-26101 + itdcndsf16qwt1.nd.gov + + + r_vm_vm-2448 + itdcndsths.nd.gov + + + r_vm_vm-28930 + itdcndsf16wp2.nd.gov + + + r_vm_vm-2204 + itdcndstrqapp1.nd.gov + + + r_vm_vm-26590 + itdcndstlapp2.nd.gov + + + r_vm_vm-26492 + itdcndsf16sowt.nd.gov + + + r_vm_vm-2549 + itdcndsttlrs.nd.gov + + + r_vm_vm-2233 + itdcndstvm03.nd.gov + + + r_vm_vm-28886 + itdcndstrwt8.nd.gov + + + r_vm_vm-19710 + itdcndsfpdb16dr.nd.gov + + + r_vm_vm-26558 + itdcndsthwp2.nd.gov + + + r_vm_vm-2031 + itdcndstrd.nd.gov + + + r_vm_vm-2590 + itdcndstrqwt.nd.gov + + + r_vm_vm-16041 + itdcndstlqwt1.nd.gov + + + r_vm_vm-26571 + itdcndstlwp.nd.gov + + + r_vm_vm-2568 + itdcndstrs.nd.gov + + + r_vm_vm-28978 + itdcndstfrdp8.nd.gov + + + r_vm_vm-26575 + itdcndstupk1.nd.gov + + + r_vm_vm-2209 + itdcndstho06.nd.gov + + + r_vm_vm-26570 + itdcndstrwp1.nd.gov + + + r_vm_vm-26100 + itdcndsf16qwt.nd.gov + + + r_vm_vm-2234 + itdcndstvm01.nd.gov + + + r_vm_vm-26562 + itdcndstrwp.nd.gov + + + r_vm_vm-21299 + itdcndspmdb.nd.gov + + + r_vm_vm-2494 + itdcndstfc.nd.gov + + + r_vm_vm-26563 + itdcndstrwp2.nd.gov + + + r_vm_vm-20117 + itdcndsltdb16.nd.gov + + + r_vm_vm-2067 + itdcndstld.nd.gov + + + r_vm_vm-2208 + itdcndsthwt6.nd.gov + + + r_vm_vm-31068 + itdcndsh16app1.nd.gov + + + r_vm_vm-2578 + itdcndstfo04.nd.gov + + + r_vm_vm-28932 + itdcndsf16wp.nd.gov + + + r_vm_vm-26578 + itdcndstrapp2.nd.gov + + + r_vm_vm-28975 + itdcndsthrdp8.nd.gov + + + r_vm_vm-2028 + itdcndstvm04.nd.gov + + + r_vm_vm-26564 + itdcndstes01.nd.gov + + + r_vm_vm-26589 + itdcndstes02.nd.gov + + + r_vm_vm-2495 + itdcndstfrdp4.nd.gov + + + r_vm_vm-26572 + itdcndstrps.nd.gov + + + r_vm_vm-26567 + itdcndstlapp1.nd.gov + + + r_vm_vm-26576 + itdcndstlwp2.nd.gov + + + r_vm_vm-25663 + itdcndspmw16.nd.gov + + + r_vm_vm-2087 + itdcndstht.nd.gov + + + r_vm_vm-26596 + itdcndstrapp1.nd.gov + + + r_vm_vm-26574 + itdcndstlrdp6.nd.gov + + + r_vm_vm-31066 + itdcnds16es01.nd.gov + + + r_vm_vm-26102 + itdcndsf16qwt2.nd.gov + + + r_vm_vm-26580 + itdcndstes03.nd.gov + + + r_vm_vm-26097 + itdcndsf16qapp1.nd.gov + + + r_vm_vm-16042 + itdcndstlqwt2.nd.gov + + + r_vm_vm-2029 + itdcndstcore.nd.gov + + + r_vm_vm-20116 + itdcndshtdb16.nd.gov + + + r_vm_vm-32214 + itdcndslscorm16.nd.gov + + + r_vm_vm-2445 + itdcndstvm02.nd.gov + + + r_vm_vm-26557 + itdcndstlps.nd.gov + + + r_vm_vm-29703 + itdcndshvm.nd.gov + + + r_vm_vm-26569 + itdcndstrrdp6.nd.gov + + + r_vm_vm-28887 + itdcndstlo08.nd.gov + + + r_vm_vm-26587 + itdcndstlscorm1.nd.gov + + + r_vm_vm-2089 + itdcndstrqapp2.nd.gov + + + r_vm_vm-2360 + itdcndstrt.nd.gov + + + r_vm_vm-2242 + itdcndstls.nd.gov + + + r_vm_vm-2486 + itdcndstlqwt.nd.gov + + + r_vm_vm-20118 + itdcndsrtdb16.nd.gov + + + r_vm_vm-24534 + itdcndsrpdb16dr.nd.gov + + + r_vm_vm-26595 + itdcndsthrdp6.nd.gov + + + r_vm_vm-2061 + itdcndstfs.nd.gov + + + r_vm_vm-2558 + itdcndsthqps.nd.gov + + + r_vm_vm-2545 + itdcndstlt.nd.gov + + + + r_folder_group-v14167 + Shared-Video-Pexip + + r_vm_vm-23603 + itdpexiprp1.nd.gov + + + r_vm_vm-1100 + itdpexipconfnd9.video.nd.gov + + + r_vm_vm-1105 + itdpexipconfnd8.video.nd.gov + + + r_vm_vm-1110 + itdpexipconfnd7.video.nd.gov + + + r_vm_vm-23602 + itdpexipmgmtnd.video.nd.gov + + + r_vm_vm-1115 + itdpexipconfnd10.video.nd.gov + + + + r_folder_group-v14554 + Shared-PeopleSoft-HigherEd + + r_vm_vm-26883 + itdcndhephip1w.nd.gov + + + r_vm_vm-21040 + itdcndhf16qwt2.nd.gov + + + r_vm_vm-19093 + itdcndhefo10.nd.gov + + + r_vm_vm-19619 + itdcndhh16qapp2.nd.gov + + + r_vm_vm-12629 + itdcndhfpdb16dr.nd.gov + + + r_vm_vm-19620 + itdcndhh16qapp1.nd.gov + + + r_vm_vm-25662 + itdcndhpmw16.nd.gov + + + r_vm_vm-26872 + itdcndhh16wp1.nd.gov + + + r_vm_vm-29701 + itdcndhfvm.nd.gov + + + r_vm_vm-22614 + itdcndhephit1.nd.gov + + + r_vm_vm-25661 + itdcndhpmapp16.nd.gov + + + r_vm_vm-19615 + itdcndhh16qwt2.nd.gov + + + r_vm_vm-19094 + itdcndhefwt10.nd.gov + + + r_vm_vm-26881 + itdcndhes03.nd.gov + + + r_vm_vm-21045 + itdcndhf16qps.nd.gov + + + r_vm_vm-26598 + itdcndhh16cgwp1.nd.gov + + + r_vm_vm-26867 + itdcndhh16ps.nd.gov + + + r_vm_vm-26876 + itdcndhh16gw.nd.gov + + + r_vm_vm-26879 + itdcndhes01.nd.gov + + + r_vm_vm-29702 + itdcndhhvm.nd.gov + + + r_vm_vm-26862 + itdcndhh16app1.nd.gov + + + r_vm_vm-26869 + itdcndhf16wp1.nd.gov + + + r_vm_vm-18604 + itdcndhehd16.nd.gov + + + r_vm_vm-26871 + itdcndhf16app1.nd.gov + + + r_vm_vm-21726 + itdcndhf16qapp1.nd.gov + + + r_vm_vm-26865 + itdcndheupk1.nd.gov + + + r_vm_vm-26880 + itdcndhf16wp2.nd.gov + + + r_vm_vm-26858 + itdcndh16es02.nd.gov + + + r_vm_vm-26863 + itdcndhes02.nd.gov + + + r_vm_vm-2210 + itdcndhevm02.nd.gov + + + r_vm_vm-26866 + itdcndhf16app2.nd.gov + + + r_vm_vm-26873 + itdcndhephire.nd.gov + + + r_vm_vm-7751 + itdcndhefwt6.nd.gov + + + r_vm_vm-26875 + itdcndhephip1.nd.gov + + + r_vm_vm-19096 + itdcndheht16.nd.gov + + + r_vm_vm-26864 + itdcndhehrdp7.nd.gov + + + r_vm_vm-7750 + itdcndhefrdp6.nd.gov + + + r_vm_vm-26868 + itdcndheurdp1.nd.gov + + + r_vm_vm-21042 + itdcndheft16.nd.gov + + + r_vm_vm-26885 + itdcndhf16wp.nd.gov + + + r_vm_vm-7749 + itdcndhefo06.nd.gov + + + r_vm_vm-25909 + itdcndhehs16.nd.gov + + + r_vm_vm-19618 + itdcndhh16qps.nd.gov + + + r_vm_vm-29547 + itdcndhf16sowt.nd.gov + + + r_vm_vm-26882 + itdcndhehrdp1.nd.gov + + + r_vm_vm-26857 + itdcndh16es03.nd.gov + + + r_vm_vm-26859 + itdcndhebooks1.nd.gov + + + r_vm_vm-22615 + itdcndhephit1w.nd.gov + + + r_vm_vm-2237 + itdcndhehwt2.nd.gov + + + r_vm_vm-2478 + itdcndhefs.nd.gov + + + r_vm_vm-26062 + itdcndhh16cgwt2.nd.gov + + + r_vm_vm-8120 + itdcndhhtdb16.nd.gov + + + r_vm_vm-19617 + itdcndhh16qwt.nd.gov + + + r_vm_vm-12467 + itdcndhftdb16.nd.gov + + + r_vm_vm-8280 + itdcndhhpdb16dr.nd.gov + + + r_vm_vm-19614 + itdcndhhcg16.nd.gov + + + r_vm_vm-25908 + itdcndhehg16.nd.gov + + + r_vm_vm-26878 + itdcndhh16app2.nd.gov + + + r_vm_vm-21039 + itdcndhf16qwt1.nd.gov + + + r_vm_vm-25659 + itdcndhpmdb16.nd.gov + + + r_vm_vm-26597 + itdcndhh16cgwp2.nd.gov + + + r_vm_vm-19613 + itdcndhh16cgwt.nd.gov + + + r_vm_vm-2511 + itdcndhevm01.nd.gov + + + r_vm_vm-21044 + itdcndhf16qapp2.nd.gov + + + r_vm_vm-26884 + itdcndh16es01.nd.gov + + + r_vm_vm-2203 + itdcndpumdh855.nd.gov + + + r_vm_vm-26061 + itdcndhh16cgwt1.nd.gov + + + r_vm_vm-17759 + itdcndhehwt10.nd.gov + + + r_vm_vm-21041 + itdcndhf16qwt.nd.gov + + + r_vm_vm-22891 + itdcndhf16ywt.nd.gov + + + r_vm_vm-26861 + itdcndhh16wp2.nd.gov + + + r_vm_vm-17760 + itdcndheho10.nd.gov + + + r_vm_vm-19095 + itdcndhefd16.nd.gov + + + r_vm_vm-22890 + itdcndhefy16.nd.gov + + + r_vm_vm-2453 + itdcndhehs.nd.gov + + + r_vm_vm-2515 + itdcndheho07.nd.gov + + + r_vm_vm-19616 + itdcndhh16qwt1.nd.gov + + + r_vm_vm-26874 + itdcndhefrdp10.nd.gov + + + r_vm_vm-26870 + itdcndhf16ps.nd.gov + + + r_vm_vm-26877 + itdcndhh16wp.nd.gov + + + + r_folder_group-v15379 + Shared-EDMS-FileNet + + r_vm_vm-1185 + itdfncm4tst.nd.gov + + + r_vm_vm-11484 + itdfnfs2tst.nd.gov + + + r_vm_vm-23318 + itdfncc4.nd.gov + + + r_vm_vm-23319 + itdfncn2.nd.gov + + + r_vm_vm-23178 + itdfnfs3.nd.gov + + + r_vm_vm-23312 + itdfncse2.nd.gov + + + r_vm_vm-23313 + itdfncc3.nd.gov + + + r_vm_vm-12878 + itdfncc3tst.nd.gov + + + r_vm_vm-23179 + itdfnfs4.nd.gov + + + r_vm_vm-2363 + itdfncn2tst.nd.gov + + + r_vm_vm-23316 + itdfncm3.nd.gov + + + r_vm_vm-1283 + itdfncm3tst.nd.gov + + + r_vm_vm-2205 + itdfndev.nd.gov + + + r_vm_vm-23315 + itdfncn3.nd.gov + + + r_vm_vm-23314 + itdfncm4.nd.gov + + + r_vm_vm-12877 + itdfncse2tst.nd.gov + + + r_vm_vm-2562 + itdfncn3tst.nd.gov + + + + r_folder_group-v14221 + Shared-Oracle + + r_vm_vm-1902 + itdoidp2.nd.gov + + + r_vm_vm-31817 + itdoemprod1.nd.gov + + + r_vm_vm-27718 + itdoemtest.nd.gov + + + r_vm_vm-27622 + itdfncc4tst.nd.gov + + + r_vm_vm-28729 + itdoemtest1.nd.gov + + + r_vm_vm-13641 + itdoidt2new.nd.gov + + + r_vm_vm-13640 + itdoidt1new.nd.gov + + + r_vm_vm-23271 + itdoemprod.nd.gov + + + + r_folder_group-v136 + Shared-Email-Exchange + + r_vm_vm-2108 + itdexchmbxman2.nd.gov + + + r_vm_vm-2106 + itdexchmbxman1.nd.gov + + + r_vm_vm-2103 + itdtexcas2.ndtestdev.nd.dev + + + r_vm_vm-2105 + itdexchcasman1.nd.gov + + + r_vm_vm-23606 + itdexchcasbis1.nd.gov + + + r_vm_vm-2057 + itdtexmbx2.ndtestdev.nd.dev + + + r_vm_vm-28451 + itdfsw.nd.gov + + + + r_folder_group-v15699 + Shared-NetMotion + + r_vm_vm-2063 + itdnetmotiont1.nd.gov + + + r_vm_vm-2451 + itdnetmotionp10.nd.gov + + + r_vm_vm-2222 + itdnetmotionp11.nd.gov + + + + r_folder_group-v14179 + Shared-SQL + + r_vm_vm-23008 + itdsql16rasp1.nd.gov + + + r_vm_vm-23009 + itdsql12rasp1.nd.gov + + + r_vm_vm-1597 + itdsql16rast1.nd.gov + + + r_vm_vm-1161 + itdsql12t1.nd.gov + + + r_vm_vm-28443 + itdsql19rasp1.nd.gov + + + r_vm_vm-1160 + itdsql12rast1.nd.gov + + + r_vm_vm-23010 + itdsql14rasp1.nd.gov + + + r_vm_vm-1569 + itdsql14t1.nd.gov + + + r_vm_vm-1568 + itdsql16t1.nd.gov + + + r_vm_vm-28043 + itdsql19rast1.nd.gov + + + r_vm_vm-25116 + itdsql19t1.nd.gov + + + r_vm_vm-1600 + itdsql14rast1.nd.gov + + + r_vm_vm-1574 + itdsql12dg1.nd.gov + + + + r_folder_group-v14217 + Shared-Email-Pioneer + + r_vm_vm-23293 + itdpioneer1.state.nd.us + + + + r_folder_group-v14222 + Shared-Workforce + + + r_folder_group-v14935 + Shared-AddressPro + + r_vm_vm-23335 + itdaddressprop1.nd.gov + + + + r_folder_group-v14220 + Shared-MySQL + + r_vm_vm-23272 + itdmysqlprod1.nd.gov + + + + r_folder_group-v15698 + Shared-PeopleSoft-Upgrade + + r_vm_vm-30511 + itdcndpum16kb.nd.gov + + + r_vm_vm-2429 + itdcndpumpin.nd.gov + + + r_vm_vm-2379 + itdcndpumpin855.nd.gov + + + r_vm_vm-2374 + itdcndpumdh.nd.gov + + + r_vm_vm-2055 + itdcndpumkb.nd.gov + + + r_vm_vm-30512 + itdcndpum16mt.nd.gov + + + r_vm_vm-2046 + itdcndpumsp.nd.gov + + + r_vm_vm-2086 + itdcndpumjr.nd.gov + + + r_vm_vm-30510 + itdcndpum16dh.nd.gov + + + r_vm_vm-30514 + itdcndpum16ja.nd.gov + + + r_vm_vm-30513 + itdcndpum16jr.nd.gov + + + + r_folder_group-v14162 + Shared-Voice-Avaya-IVR + + r_vm_vm-24356 + itdvpas1man.nd.gov + + + r_vm_vm-24358 + itdvpas2man.nd.gov + + + r_vm_vm-23236 + itdvpepmbis.nd.gov + + + r_vm_vm-1369 + Itdvpspeech2man.nd.gov + + + r_vm_vm-24357 + itdvpas3man.nd.gov + + + r_vm_vm-24388 + itdvpas4man.nd.gov + + + + r_folder_group-v14216 + Shared-Drupal + + + r_folder_group-v14941 + Shared-SCCM + + r_vm_vm-23266 + itdsccmwsus1.nd.gov + + + + r_folder_group-v14939 + Shared-HEAT + + r_vm_vm-2214 + itdheatt1.nd.gov + + + r_vm_vm-23288 + itdheatprod1.nd.gov + + + + r_folder_group-v14161 + Shared-Voice-Avaya-ECAS + + r_vm_vm-23238 + itdecas2.nd.gov + + + + r_folder_group-v14880 + Shared-EDMS-eForms + + r_vm_vm-23320 + itdeforms.itd.nd.gov + + + r_vm_vm-2037 + itdeformstst.itd.nd.gov + + + + r_folder_group-v14218 + Shared-Email-SecureMail + + + r_folder_group-v15733 + Shared-Teammate + + r_vm_vm-6431 + itdteamt1.nd.gov + + + + r_folder_group-v14937 + Shared-Email-ListServ + + r_vm_vm-26886 + itdlist.nd.gov + + + r_vm_vm-18876 + itdlistdev.nd.gov + + + + r_folder_group-v14160 + Shared-Voice-Avaya + + r_vm_vm-19650 + itdmancmess8.nd.gov + + + r_vm_vm-23382 + itdbiscmsvra.nd.gov + + + r_vm_vm-23241 + itdbiscms.nd.gov + + + r_vm_vm-23242 + itdwfoaes4.nd.gov + + + r_vm_vm-23244 + itdbissm1mgt8.nd.gov + + + r_vm_vm-19013 + itdaads.nd.gov + + + r_vm_vm-23243 + itdbissysmgr8.nd.gov + + + r_vm_vm-1321 + itdvpmpp2man.nd.gov + + + r_vm_vm-28495 + itdavayarec.nd.gov + + + r_vm_vm-23245 + itdbisweblm.nd.gov + + + + r_folder_group-v14940 + Shared-IIS + + r_vm_vm-26554 + itdwww3.nd.gov + + + + r_folder_group-v14942 + Shared-Video-Renovo + + r_vm_vm-19449 + itdk12vidappt1.nd.gov + + + r_vm_vm-26603 + itdk12vidwebp1.nd.gov + + + r_vm_vm-26604 + itdk12vidappp1.nd.gov + + + r_vm_vm-19448 + itdk12vidwebt1.nd.gov + + + + r_folder_group-v14215 + Shared-Apache + + r_vm_vm-23333 + itdapachep3.nd.gov + + + r_vm_vm-23332 + itdapachep1a.nd.gov + + + r_vm_vm-1920 + itdapachet3.nd.gov + + + + r_folder_group-v14936 + Shared-Cognos + + r_vm_vm-23331 + itdcogentprd1.nd.gov + + + + r_folder_group-v14938 + Shared-Email-Lync + + r_vm_vm-23297 + itdskypeedge1.nd.gov + + + r_vm_vm-23296 + itdskypedir1.nd.gov + + + + r_folder_group-v14163 + Shared-Voice-Avaya-WebConf + + r_vm_vm-23227 + itdbisaac.nd.gov + + + + r_folder_group-v14168 + Shared-Video-vBrick + + r_vm_vm-23383 + itdvbrickdb1.video.nd.gov + + + r_vm_vm-23386 + itdvbrickrev2.video.nd.gov + + + r_vm_vm-23384 + itdvbrickes1.video.nd.gov + + + r_vm_vm-23387 + itdvbrickrev.video.nd.gov + + + r_vm_vm-23385 + itdvbrickdme1.video.nd.gov + + + + r_folder_group-v15740 + Shared-MasterDataMGT-MC + + + r_folder_group-v15703 + Shared-EDMS-Riptide + + r_vm_vm-1225 + itdedmst1.nd.gov + + + + r_folder_group-v15713 + Shared-K12-ActiveDirectory + + r_vm_vm-2217 + itdk12testdc3.k12tst.nd.us + + + + r_folder_group-v25368 + Shared-Postgres + + r_vm_vm-25365 + itdpgtest1.nd.gov + + + + r_folder_group-v14164 + Shared-Voice-VoiceMail + + r_vm_vm-23186 + itdaam71storage.nd.gov + + + r_vm_vm-18875 + itdaam71as2.nd.gov + + + + r_folder_group-v14219 + Shared-MasterDataMgt-MCI + + r_vm_vm-32216 + itdmdmprod1.nd.gov + + + r_vm_vm-23276 + itdmciprod2.nd.gov + + + r_vm_vm-23275 + itdmciprod.nd.gov + + + r_vm_vm-32217 + itdmdmprod2.nd.gov + + + r_vm_vm-16477 + itdmdmbuildws.nd.gov + + + r_vm_vm-24997 + itdmdmtest2.nd.gov + + + r_vm_vm-16449 + itdmdmbuild2.nd.gov + + + r_vm_vm-24996 + itdmdmtest1.nd.gov + + + r_vm_vm-24994 + itdmdmuat1.nd.gov + + + r_vm_vm-18480 + itdmdmstg1.nd.gov + + + r_vm_vm-24024 + itdmdmsit1.nd.gov + + + r_vm_vm-16448 + itdmdmbuild1.nd.gov + + + + r_folder_group-v15714 + Shared-EDMS-SQL + + r_vm_vm-1474 + itdsqledmsp1dr.nd.gov + + + r_vm_vm-1291 + itdsqledmst1.nd.gov + + + + r_folder_group-v15123 + Shared-PowerSchool + + r_vm_vm-23538 + itdps-stalphons.nd.gov + + + r_vm_vm-23598 + itdps-applecree.nd.gov + + + r_vm_vm-23435 + itdps-centralca.nd.gov + + + r_vm_vm-23521 + itdps-thompson.nd.gov + + + r_vm_vm-23516 + itdps-medina.nd.gov + + + r_vm_vm-23477 + itdps-oakes.nd.gov + + + r_vm_vm-23466 + itdps-fargodb.nd.gov + + + r_vm_vm-23576 + itdps-newenglan.nd.gov + + + r_vm_vm-23467 + itdps-lamoure.nd.gov + + + r_vm_vm-23393 + itdps-westfatst.nd.gov + + + r_vm_vm-28458 + itdps-richland.nd.gov + + + r_vm_vm-23395 + itdps-beulah.nd.gov + + + r_vm_vm-23397 + itdps-orcs.nd.gov + + + r_vm_vm-28491 + itdps-hankinson.nd.gov + + + r_vm_vm-23596 + itdps-northstar.nd.gov + + + r_vm_vm-28454 + itdps-grandf1.nd.gov + + + r_vm_vm-23474 + itdps-minottst.nd.gov + + + r_vm_vm-23488 + itdps-svactc.nd.gov + + + r_vm_vm-23430 + itdps-dunseith.nd.gov + + + r_vm_vm-23572 + itdps-stmichael.nd.gov + + + r_vm_vm-23471 + itdps-dakotamem.nd.gov + + + r_vm_vm-28472 + itdps-goodrich.nd.gov + + + r_vm_vm-23464 + itdps-enderlin.nd.gov + + + r_vm_vm-23394 + itdps-kiddercou.nd.gov + + + r_vm_vm-23580 + itdps-sawyer.nd.gov + + + r_vm_vm-23402 + itdps-hmb.nd.gov + + + r_vm_vm-28468 + itdps-lakota.nd.gov + + + r_vm_vm-23542 + itdps-mtpleasan.nd.gov + + + r_vm_vm-23454 + itdps-bismarrpt.nd.gov + + + r_vm_vm-23412 + itdps-wyndmere.nd.gov + + + r_vm_vm-23501 + itdps-wilton.nd.gov + + + r_vm_vm-23475 + itdps-manvel.nd.gov + + + r_vm_vm-23457 + itdps-burkecent.nd.gov + + + r_vm_vm-23498 + itdps-belfield.nd.gov + + + r_vm_vm-28470 + itdps-milnor.nd.gov + + + r_vm_vm-23557 + itdps-willisrpt.nd.gov + + + r_vm_vm-23595 + itdps-powerslak.nd.gov + + + r_vm_vm-23533 + itdps-glenullin.nd.gov + + + r_vm_vm-28482 + itdps-minotdb.nd.gov + + + r_vm_vm-23567 + itdps-fairmount.nd.gov + + + r_vm_vm-23442 + itdps-maddock.nd.gov + + + r_vm_vm-23443 + itdps-willisdb.nd.gov + + + r_vm_vm-23541 + itdps-hettinger.nd.gov + + + r_vm_vm-23535 + itdps-hopepage.nd.gov + + + r_vm_vm-23460 + itdps-centralva.nd.gov + + + r_vm_vm-28492 + itdps-oberon.nd.gov + + + r_vm_vm-23470 + itdps-tioga.nd.gov + + + r_vm_vm-23445 + itdps-napoleon.nd.gov + + + r_vm_vm-23406 + itdps-newtown.nd.gov + + + r_vm_vm-23545 + itdps-roosevelt.nd.gov + + + r_vm_vm-28490 + itdps-warwick.nd.gov + + + r_vm_vm-23593 + itdps-washburn.nd.gov + + + r_vm_vm-23573 + itdps-yellowsto.nd.gov + + + r_vm_vm-28484 + itdps-halliday.nd.gov + + + r_vm_vm-23524 + itdps-finleysha.nd.gov + + + r_vm_vm-23481 + itdps-minot1.nd.gov + + + r_vm_vm-23582 + itdps-hazen.nd.gov + + + r_vm_vm-23515 + itdps-mandan1.nd.gov + + + r_vm_vm-23556 + itdps-ray.nd.gov + + + r_vm_vm-23483 + itdps-bismarqa.nd.gov + + + r_vm_vm-23577 + itdps-northwood.nd.gov + + + r_vm_vm-23485 + itdps-lewisandc.nd.gov + + + r_vm_vm-23525 + itdps-bismar4.nd.gov + + + r_vm_vm-23422 + itdps-wing.nd.gov + + + r_vm_vm-23461 + itdps-lisbon.nd.gov + + + r_vm_vm-23517 + itdps-linton.nd.gov + + + r_vm_vm-23555 + itdps-wndctc.nd.gov + + + r_vm_vm-28473 + itdps-westfa1.nd.gov + + + r_vm_vm-23411 + itdps-gacklestr.nd.gov + + + r_vm_vm-23420 + itdps-strasburg.nd.gov + + + r_vm_vm-28493 + itdps-beach.nd.gov + + + r_vm_vm-23508 + itdps-fargo3.nd.gov + + + r_vm_vm-23493 + itdps-wahpeton.nd.gov + + + r_vm_vm-23426 + itdps-lidgerwoo.nd.gov + + + r_vm_vm-28453 + itdps-hatton.nd.gov + + + r_vm_vm-23529 + itdps-kensal.nd.gov + + + r_vm_vm-23512 + itdps-newrockfo.nd.gov + + + r_vm_vm-23407 + itdps-tgu.nd.gov + + + r_vm_vm-23476 + itdps-minnewauk.nd.gov + + + r_vm_vm-23520 + itdps-northbord.nd.gov + + + r_vm_vm-23427 + itdps-griggscou.nd.gov + + + r_vm_vm-23480 + itdps-midkota.nd.gov + + + r_vm_vm-23439 + itdps-sterling.nd.gov + + + r_vm_vm-23581 + itdps-scranton.nd.gov + + + r_vm_vm-28457 + itdps-update.nd.gov + + + r_vm_vm-23450 + itdps-fargotst.nd.gov + + + r_vm_vm-23554 + itdps-ndsd.nd.gov + + + r_vm_vm-23558 + itdps-fordville.nd.gov + + + r_vm_vm-23507 + itdps-bowbells.nd.gov + + + r_vm_vm-23561 + itdps-maplevall.nd.gov + + + r_vm_vm-23551 + itdps-velva.nd.gov + + + r_vm_vm-23486 + itdps-underwood.nd.gov + + + r_vm_vm-23446 + itdps-kindred.nd.gov + + + r_vm_vm-23425 + itdps-leeds.nd.gov + + + r_vm_vm-28462 + itdps-northernc.nd.gov + + + r_vm_vm-23415 + itdps-dickinrpt.nd.gov + + + r_vm_vm-23513 + itdps-mandandb.nd.gov + + + r_vm_vm-28464 + itdps-westfadb.nd.gov + + + r_vm_vm-23409 + itdps-willistst.nd.gov + + + r_vm_vm-23497 + itdps-mayville.nd.gov + + + r_vm_vm-23579 + itdps-fargo2.nd.gov + + + r_vm_vm-23547 + itdps-grafton.nd.gov + + + r_vm_vm-23458 + itdps-parshall.nd.gov + + + r_vm_vm-23462 + itdps-hebron.nd.gov + + + r_vm_vm-28460 + itdps-fessenden.nd.gov + + + r_vm_vm-23562 + itdps-harvey.nd.gov + + + r_vm_vm-23522 + itdps-minot2.nd.gov + + + r_vm_vm-28486 + itdps-stthomas.nd.gov + + + r_vm_vm-28488 + itdps-kenmare.nd.gov + + + r_vm_vm-28466 + itdps-glenburn.nd.gov + + + r_vm_vm-23404 + itdps-deslacsbu.nd.gov + + + r_vm_vm-23417 + itdps-minotrpt.nd.gov + + + r_vm_vm-23489 + itdps-bismar2.nd.gov + + + r_vm_vm-28467 + itdps-dickindb.nd.gov + + + r_vm_vm-23400 + itdps-willis1.nd.gov + + + r_vm_vm-23528 + itdps-starkweat.nd.gov + + + r_vm_vm-23441 + itdps-mandan2.nd.gov + + + r_vm_vm-28480 + itdps-killdeer.nd.gov + + + r_vm_vm-23518 + itdps-dividecou.nd.gov + + + r_vm_vm-23534 + itdps-alexander.nd.gov + + + r_vm_vm-28474 + itdps-surrey.nd.gov + + + r_vm_vm-23434 + itdps-watfordci.nd.gov + + + r_vm_vm-23552 + itdps-ashley.nd.gov + + + r_vm_vm-28476 + itdps-munich.nd.gov + + + r_vm_vm-23546 + itdps-garrison.nd.gov + + + r_vm_vm-23413 + itdps-bismar3.nd.gov + + + r_vm_vm-23594 + itdps-wolford.nd.gov + + + r_vm_vm-23468 + itdps-turtlelak.nd.gov + + + r_vm_vm-23392 + itdps-ditrinity.nd.gov + + + r_vm_vm-23398 + itdps-eightmile.nd.gov + + + r_vm_vm-23588 + itdps-elginnewl.nd.gov + + + r_vm_vm-23548 + itdps-testslds.nd.gov + + + r_vm_vm-23408 + itdps-ellendale.nd.gov + + + r_vm_vm-23440 + itdps-emerado.nd.gov + + + r_vm_vm-28475 + itdps-anamoosed.nd.gov + + + r_vm_vm-23490 + itdps-valleycit.nd.gov + + + r_vm_vm-23532 + itdps-rolette.nd.gov + + + r_vm_vm-23396 + itdps-dickin2.nd.gov + + + r_vm_vm-23560 + itdps-grandfqa.nd.gov + + + r_vm_vm-23530 + itdps-northsarg.nd.gov + + + r_vm_vm-23452 + itdps-mohall.nd.gov + + + r_vm_vm-23586 + itdps-southhear.nd.gov + + + r_vm_vm-23416 + itdps-westfarpt.nd.gov + + + r_vm_vm-23494 + itdps-edmore.nd.gov + + + r_vm_vm-23549 + itdps-grandf2.nd.gov + + + r_vm_vm-23399 + itdps-montpelie.nd.gov + + + r_vm_vm-23544 + itdps-westhope.nd.gov + + + r_vm_vm-23444 + itdps-grandf3.nd.gov + + + r_vm_vm-28487 + itdps-dickin1.nd.gov + + + r_vm_vm-23597 + itdps-bowman.nd.gov + + + r_vm_vm-23600 + itdps-mandanqa.nd.gov + + + r_vm_vm-23604 + itdps-fargorpt.nd.gov + + + r_vm_vm-23506 + itdps-cddlc.nd.gov + + + r_vm_vm-23575 + itdps-ndschools.nd.gov + + + r_vm_vm-28463 + itdps-mapleton.nd.gov + + + r_vm_vm-23469 + itdps-richardto.nd.gov + + + r_vm_vm-23484 + itdps-mandanrpt.nd.gov + + + r_vm_vm-23523 + itdps-carringto.nd.gov + + + r_vm_vm-23502 + itdps-barnescou.nd.gov + + + r_vm_vm-28469 + itdps-southprai.nd.gov + + + r_vm_vm-23449 + itdps-newburg.nd.gov + + + r_vm_vm-23495 + itdps-newsalem.nd.gov + + + r_vm_vm-23539 + itdps-cavalier.nd.gov + + + r_vm_vm-23436 + itdps-stjohn.nd.gov + + + r_vm_vm-23503 + itdps-srctc.nd.gov + + + r_vm_vm-23419 + itdps-langdon.nd.gov + + + r_vm_vm-23496 + itdps-litchvill.nd.gov + + + r_vm_vm-28489 + itdps-selfridge.nd.gov + + + r_vm_vm-23531 + itdps-zeeland.nd.gov + + + r_vm_vm-23590 + itdps-rugby.nd.gov + + + r_vm_vm-28461 + itdps-bismardb.nd.gov + + + r_vm_vm-23429 + itdps-hfsm.nd.gov + + + r_vm_vm-23428 + itdps-devilslak.nd.gov + + + r_vm_vm-28465 + itdps-fargo4.nd.gov + + + r_vm_vm-28456 + itdps-larimore.nd.gov + + + r_vm_vm-23585 + itdps-westfa3.nd.gov + + + r_vm_vm-23459 + itdps-kulm.nd.gov + + + r_vm_vm-23433 + itdps-flasher.nd.gov + + + r_vm_vm-23578 + itdps-grandfdb.nd.gov + + + r_vm_vm-23465 + itdps-pingreebu.nd.gov + + + r_vm_vm-23540 + itdps-mcclusky.nd.gov + + + r_vm_vm-23504 + itdps-sargentce.nd.gov + + + r_vm_vm-23589 + itdps-solen.nd.gov + + + r_vm_vm-23447 + itdps-fargo1.nd.gov + + + r_vm_vm-23500 + itdps-westfa2.nd.gov + + + r_vm_vm-23599 + itdps-northvall.nd.gov + + + r_vm_vm-28471 + itdps-stjohnswa.nd.gov + + + r_vm_vm-28478 + itdps-parkriver.nd.gov + + + r_vm_vm-23390 + itdps-minot3.nd.gov + + + r_vm_vm-23570 + itdps-willis2.nd.gov + + + r_vm_vm-23527 + itdps-midway.nd.gov + + + r_vm_vm-23587 + itdps-minto.nd.gov + + + r_vm_vm-23492 + itdps-edgeley.nd.gov + + + r_vm_vm-23479 + itdps-bismar1.nd.gov + + + r_vm_vm-23566 + itdps-max.nd.gov + + + r_vm_vm-28481 + itdps-dakotapra.nd.gov + + + r_vm_vm-28494 + itdps-valleyedi.nd.gov + + + r_vm_vm-28477 + itdps-billingsc.nd.gov + + + r_vm_vm-23574 + itdps-nedrose.nd.gov + + + r_vm_vm-23448 + itdps-fourwinds.nd.gov + + + r_vm_vm-28483 + itdps-drayton.nd.gov + + + r_vm_vm-23536 + itdps-centersta.nd.gov + + + r_vm_vm-28479 + itdps-stanley.nd.gov + + + r_vm_vm-23568 + itdps-jamestown.nd.gov + + + r_vm_vm-28455 + itdps-mottregen.nd.gov + + + r_vm_vm-28459 + itdps-bottineau.nd.gov + + + r_vm_vm-23514 + itdps-hillsboro.nd.gov + + + r_vm_vm-23564 + itdps-district8.nd.gov + + + r_vm_vm-23592 + itdps-grandfrpt.nd.gov + + + r_vm_vm-23491 + itdps-wishek.nd.gov + + + r_vm_vm-28485 + itdps-ftyates.nd.gov + + + r_vm_vm-23550 + itdps-grenora.nd.gov + + + r_vm_vm-23505 + itdps-images.nd.gov + + + + r_folder_group-v15712 + Shared-SQL-DR + + r_vm_vm-30880 + itdsql19p1dr.nd.gov + + + r_vm_vm-1460 + itdsql14p2dr.nd.gov + + + r_vm_vm-1447 + itdsql16p1dr.nd.gov + + + r_vm_vm-1471 + itdsql14p1dr.nd.gov + + + r_vm_vm-1469 + itdsql12t1dr.nd.gov + + + r_vm_vm-1448 + itdsql12p1dr.nd.gov + + + r_vm_vm-18481 + itdsql16p3dr.nd.gov + + + + r_folder_group-v15719 + Shared-SharePoint-SQL + + r_vm_vm-1591 + itdsql12spt1.nd.gov + + + + r_folder_group-v15725 + Shared-SharePoint-DR-SQL + + r_vm_vm-1573 + itdsql12spp1dr.nd.gov + + + + r_folder_group-v15735 + Shared-SharePoint-DR + + r_vm_vm-2574 + itdspsprod1dr13.nd.gov + + + + r_folder_group-v14748 + Shared-Email-Rightfax + + r_vm_vm-28452 + itdrfax.nd.gov + + + + + r_folder_group-v15537 + NDUS + + + r_folder_group-v15548 + PNR + + + r_folder_group-v15525 + DOT + + r_folder_group-v16650 + DOT-Shared-IIS + + r_vm_vm-16211 + itddotnetet1.nd.gov + + + + r_folder_group-v15731 + DOT-RoadTest + + r_vm_vm-2428 + itddotrtt1.nd.gov + + + + r_folder_group-v24537 + DOT-DTIMS + + r_vm_vm-24533 + itddotdtimst1.nd.gov + + + + r_folder_group-v131 + DOT-STARS + + r_vm_vm-23268 + itddotmvp2.nd.gov + + + r_vm_vm-23267 + itddotmvp1.nd.gov + + + r_vm_vm-1577 + itdsqlmvt1.nd.gov + + + r_vm_vm-2236 + itddotappt1.nd.gov + + + r_vm_vm-23270 + itddotmvp3.nd.gov + + + r_vm_vm-23269 + itddotfcr1.nd.gov + + + r_vm_vm-2369 + itddotmvs2.nd.gov + + + r_vm_vm-1266 + itdsqlmvp2.nd.gov + + + r_vm_vm-1601 + itdsqlmvt2.nd.gov + + + r_vm_vm-2218 + itddotmvs3.nd.gov + + + r_vm_vm-9549 + itddotmvs1.nd.gov + + + + + r_folder_group-v15536 + Infra + + r_folder_group-v15383 + Infra-Monitoring-Solarwinds + + r_vm_vm-8119 + itdslrwndstest.nd.gov + + + r_vm_vm-23327 + itdslrwnds.nd.gov + + + r_vm_vm-23325 + itdslrwndspoll2.nd.gov + + + r_vm_vm-23326 + itdslrwndspoll1.nd.gov + + + + r_folder_group-v14213 + Infra-Wiki + + r_vm_vm-23353 + itdwikip1.nd.gov + + + + r_folder_group-v15701 + Infra-QA-LoadRunner + + r_vm_vm-6406 + itdhploadtest05.nd.gov + + + r_vm_vm-6403 + itdhploadtest02.nd.gov + + + r_vm_vm-6405 + itdhploadtest04.nd.gov + + + r_vm_vm-6370 + itdhploadtest01.nd.gov + + + r_vm_vm-6371 + itdldruncntrl1.nd.gov + + + r_vm_vm-6404 + itdhploadtest03.nd.gov + + + r_vm_vm-6433 + itdhploadtest06.nd.gov + + + + r_folder_group-v14202 + Infra-Email-Relay + + r_vm_vm-23308 + apprelay2.nd.gov + + + r_vm_vm-23309 + apprelay1.nd.gov + + + + r_folder_group-v14923 + Infra-LicenseMgt-KMS + + r_vm_vm-23310 + itdkms2.nd.gov + + + + r_folder_group-v14924 + Infra-LicenseMgt-Misc + + r_vm_vm-23311 + itdkms1.nd.gov + + + + r_folder_group-v14927 + Infra-Networking-Wireless + + r_vm_vm-29262 + itdnps2.nd.gov + + + r_vm_vm-26096 + itdarubamm2.nd.gov + + + + r_folder_group-v14206 + Infra-OneView + + r_vm_vm-23340 + itdoneviewp1.nd.gov + + + + r_folder_group-v26551 + Infra-Security-Demisto + + r_vm_vm-26552 + itddemistoeip1.nd.gov + + + r_vm_vm-30780 + itddemistoeit1.nd.gov + + + r_vm_vm-30706 + itddemistoeip2.nd.gov + + + + r_folder_group-v14929 + Infra-Security-AntiVirus-Traps + + r_vm_vm-23378 + itdpaesmint1.nd.gov + + + r_vm_vm-23367 + itdpaesmext1.nd.gov + + + + r_folder_group-v14926 + Infra-MoveIT + + r_vm_vm-2548 + itdmidmzt1.nd.gov + + + r_vm_vm-23329 + itdmiautop1.nd.gov + + + r_vm_vm-23380 + itdmitransferp1.nd.gov + + + r_vm_vm-26607 + itdmigateway.nd.gov + + + r_vm_vm-2220 + itdmicent1.nd.gov + + + r_vm_vm-23330 + itdmicenp1.nd.gov + + + r_vm_vm-19579 + itdmigatewayt1.nd.gov + + + + r_folder_group-v14557 + Infra-ADFS + + r_vm_vm-15629 + itdadfspxyt6.testnd.gov + + + r_vm_vm-23294 + itdadfsintldp1.nd.gov + + + r_vm_vm-15628 + itdadfst6.testnd.gov + + + r_vm_vm-23295 + itdadfsldp1.nd.gov + + + + r_folder_group-v14930 + Infra-Security-CertificateAuthority + + r_vm_vm-23371 + itdca6.nd.gov + + + r_vm_vm-23372 + itdca5.nd.gov + + + r_vm_vm-23370 + itdcaroot2.nd.gov + + + + r_folder_group-v15382 + Infra-Servers-SCCM + + r_vm_vm-23368 + itdsccmp2.nd.gov + + + + r_folder_group-v15696 + Infra-VMware + + r_vm_vm-27301 + itdvmvc2.nd.gov + + + r_vm_vm-742 + itdvmsrm2.nd.gov + + + r_vm_vm-2585 + itdvmvcp2script.nd.gov + + + + r_folder_group-v14928 + Infra-Print + + r_vm_vm-23344 + itdprint1e.nd.gov + + + r_vm_vm-23350 + itdprint1f.nd.gov + + + r_vm_vm-23346 + itdprint1d.nd.gov + + + r_vm_vm-23345 + itdprint1g.nd.gov + + + r_vm_vm-23348 + itdprint2a.nd.gov + + + r_vm_vm-23351 + itdprint1h.nd.gov + + + + r_folder_group-v28924 + Infra-NDLoginProxy + + r_vm_vm-28851 + itdb2cpxyt1.nd.gov + + + r_vm_vm-28852 + itdb2cpxyt2.nd.gov + + + + r_folder_group-v15738 + Infra-Monitoring-Solarwinds-SQL + + r_vm_vm-23187 + itdsql16solar.nd.gov + + + + r_folder_group-v15718 + Infra-Storage + + r_vm_vm-23366 + itdibmna1.nd.gov + + + r_vm_vm-8630 + itdmdnstghyp1.nd.gov + + + + r_folder_group-v28073 + Infra-Servers-WindowsAdmin + + r_vm_vm-27398 + itdwact1.nd.gov + + + + r_folder_group-v14203 + Infra-LDAP-TDS + + r_vm_vm-1895 + itdsdsp2a.nd.gov + + + r_vm_vm-1917 + itdsdst2a.nd.gov + + + r_vm_vm-23118 + itdsdsp1a.nd.gov + + + + r_folder_group-v15697 + Infra-SpectrumProtect-VE + + r_vm_vm-2584 + itdvmvcp2-linmp.nd.gov + + + r_vm_vm-24123 + itdvmvc2spdm01.nd.gov + + + r_vm_vm-24122 + itdvmvc2spvcli.nd.gov + + + r_vm_vm-2583 + itdvmvcp2-winmp.nd.gov + + + + r_folder_group-v15709 + Infra-Security-MFA-SafeNet-SQL + + r_vm_vm-30779 + itdmfasql16p2.nd.gov + + + r_vm_vm-1264 + itdmfasql2.nd.gov + + + + r_folder_group-v14211 + Infra-SKLM + + r_vm_vm-1891 + itdmdnsklm1.nd.gov + + + r_vm_vm-23165 + itdbissklm1.nd.gov + + + + r_folder_group-v15070 + Infra-Security-MFA-AzureMFA + + r_vm_vm-26893 + itdmfaportal1.nd.gov + + + r_vm_vm-26891 + itdmfaserver1.nd.gov-DLDelete20200624 + + + + r_folder_group-v21859 + Infra-NetApp + + r_vm_vm-26890 + itdnaum1.nd.gov + + + + r_folder_group-v14922 + Infra-Desktop-Encryption + + r_vm_vm-23307 + itdmbam1.nd.gov + + + + r_folder_group-v15071 + Infra-Security-MFA-SafeNet + + r_vm_vm-2510 + itdmfat1.nd.gov + + + r_vm_vm-2591 + itdmfat2.nd.gov + + + r_vm_vm-2432 + itdmfa2.nd.gov + + + r_vm_vm-1596 + itdmfatsql1.nd.gov + + + r_vm_vm-23375 + itdmfa3.nd.gov + + + + r_folder_group-v15710 + Infra-VMware-DR + + r_vm_vm-22934 + itdvmvrsmdn1.nd.gov + + + r_vm_vm-22931 + itdvmvra2.nd.gov + + + r_vm_vm-22933 + itdvmvrsmdn2.nd.gov + + + + r_folder_group-v14210 + Infra-Servers-Satellite + + r_vm_vm-28928 + itdsatellite1.nd.gov + + + r_vm_vm-1742 + itdsatellitet1.nd.gov + + + r_vm_vm-1897 + itdsattest1.nd.gov + + + r_vm_vm-23369 + itdsatellitep1.nd.gov + + + r_vm_vm-1898 + itdsattest2.nd.gov + + + r_vm_vm-1892 + itdsattest3.nd.gov + + + + r_folder_group-v15726 + Infra-ActiveDirectory + + r_vm_vm-12470 + itddc19.nd.gov + + + r_vm_vm-15627 + itddct4.testnd.gov + + + + r_folder_group-v15069 + Infra-ADFS-DirSync + + r_vm_vm-23300 + itddsync2.nd.gov + + + r_vm_vm-23301 + itddsync1.nd.gov + + + + r_folder_group-v19012 + Infra-PTA + + r_vm_vm-19010 + itdpta1.nd.gov + + + + r_folder_group-v15739 + Infra-Servers-SCCM-SQL + + r_vm_vm-23381 + itdsql16sccm.nd.gov + + + + r_folder_group-v14208 + Infra-Servers-Ansible + + r_vm_vm-23162 + itdgitlab.nd.gov + + + r_vm_vm-23377 + itdansible.nd.gov + + + + r_folder_group-v15720 + Infra-SoftDev-RDS + + r_vm_vm-11485 + itdsftdevrds2.nd.gov + + + r_vm_vm-2373 + itdsftdevrds1.nd.gov + + + + r_folder_group-v22239 + Infra-F5 + + r_vm_vm-22205 + itdf5sharedt2.nd.gov + + + + r_folder_group-v14788 + Infra-SoftDev-TFS + + r_vm_vm-23166 + itdtfsp2.nd.gov + + + + r_folder_group-v15727 + Infra-QA-ScanTools-AppScan + + r_vm_vm-2513 + itdappscandas1.nd.gov + + + r_vm_vm-2490 + itdappscanent.nd.gov + + + + r_folder_group-v15704 + Infra-LogMGT-Splunk + + r_vm_vm-1743 + itdswdsplunk1.nd.gov + + + + r_folder_group-v15711 + Infra-Security-MFA-SafeNet-Linux + + r_vm_vm-1746 + itdmfat3.nd.gov + + + r_vm_vm-1747 + itdmfa5.nd.gov + + + + r_folder_group-v14204 + Infra-LoadBalancer + + r_vm_vm-1875 + itdintldtest2.nd.gov + + + r_vm_vm-23322 + itdintldprod2.nd.gov + + + r_vm_vm-23321 + itdintldprod1.nd.gov + + + + r_folder_group-v15716 + Infra-Search + + r_vm_vm-11311 + itdsearchbloxt1.nd.gov + + + + r_folder_group-v15724 + Infra-WINS + + r_vm_vm-2419 + ns7.nd.gov + + + + r_folder_group-v15734 + Infra-DFS + + r_vm_vm-2442 + itddfsp2.itd.nd.gov + + + r_vm_vm-27399 + itddfsp4.nd.gov + + + + r_folder_group-v14209 + Infra-Servers-OELR + + r_vm_vm-23379 + itdoraclesatp1.nd.gov + + + + r_folder_group-v14177 + Infra-PasswordState + + r_vm_vm-23608 + itdpv2.nd.gov + + + r_vm_vm-23609 + itdapv.nd.gov + + + + r_folder_group-v14207 + Infra-Proxy + + r_vm_vm-23361 + itdextrp6.nd.gov + + + r_vm_vm-23363 + itdextrp8.nd.gov + + + r_vm_vm-28820 + itdintrplbt3.nd.gov + + + r_vm_vm-1893 + itdextrpt1.nd.gov + + + r_vm_vm-1876 + itdextldtest1.nd.gov + + + r_vm_vm-23355 + itdextldprod3.nd.gov + + + r_vm_vm-1923 + itdextrpt2.nd.gov + + + r_vm_vm-1900 + itdintrpsit1.nd.gov + + + r_vm_vm-23364 + itdextldprod2.nd.gov + + + r_vm_vm-28819 + itdintrplbt1.nd.gov + + + r_vm_vm-23358 + itdextrp2.nd.gov + + + r_vm_vm-29076 + itdintrpmgrp1.nd.gov + + + r_vm_vm-1874 + itdextldtest2.nd.gov + + + r_vm_vm-23356 + itdextrp3.nd.gov + + + r_vm_vm-23359 + itdextldprod1.nd.gov + + + r_vm_vm-28817 + itdintrpt3.nd.gov + + + r_vm_vm-23365 + itdextrp7.nd.gov + + + r_vm_vm-1871 + itdextldtest3.nd.gov + + + r_vm_vm-28818 + itdintrplbt2.nd.gov + + + r_vm_vm-23354 + itdextrp4.nd.gov + + + r_vm_vm-23357 + itdintrp1.nd.gov + + + r_vm_vm-23292 + itdegressrp1.nd.gov + + + r_vm_vm-28816 + itdintrpt2.nd.gov + + + r_vm_vm-29881 + itdintrpsit3.nd.gov + + + r_vm_vm-23362 + itdextrp1.nd.gov + + + r_vm_vm-23360 + itdextrp5.nd.gov + + + r_vm_vm-1904 + itdintrpt1.nd.gov + + + + r_folder_group-v14212 + Infra-UC4 + + r_vm_vm-23376 + itduc4p1.itd.nd.gov + + + + r_folder_group-v14205 + Infra-LogMGT-Logstash + + + + + r_folder_group-h4 + host + + r_computeResource_domain-s32185 + itdmdnvm-win04.nd.gov + + r_host_host-2027 + itdmdnvm-win04.nd.gov + + + r_resource_resgroup-32186 + Resources + + + + r_computeResource_domain-c63 + LINUX2 + + r_host_host-1908 + itdappvm240.nd.gov + + + r_host_host-26824 + itdmdnvm-lin02.nd.gov + + + r_host_host-1706 + itdmdnvm-lin01.nd.gov + + + r_host_host-2958 + itdappvm238.nd.gov + + + r_host_host-1877 + itdappvm239.nd.gov + + + r_resource_resgroup-64 + Resources + + + + r_computeResource_domain-c65 + ODM2 + + r_host_host-1128 + itdmdnvm-odm01.nd.gov + + + r_resource_resgroup-66 + Resources + + + + r_computeResource_domain-c32183 + WINDOWS2b + + r_resource_resgroup-32184 + Resources + + + + r_computeResource_domain-c30884 + WINDOWS2 + + r_host_host-2072 + itdmdnvm-gen03.nd.gov + + + r_host_host-2454 + itdmdnvm-win01.nd.gov + + + r_host_host-2516 + itdmdnvm-win03.nd.gov + + + r_host_host-2336 + itdmdnvm-gen02.nd.gov + + + r_host_host-2171 + itdmdnvm-gen04.nd.gov + + + r_host_host-2395 + itdmdnvm-win02.nd.gov + + + r_host_host-9 + itdmdnvm-gen01.nd.gov + + + r_resource_resgroup-30885 + Resources + + + + r_computeResource_domain-c61 + AVAYA2 + + r_host_host-11839 + itdmdnvm-av01.nd.gov + + + r_host_host-11873 + itdmdnvm-av03.nd.gov + + + r_host_host-11938 + itdmdnvm-av02.nd.gov + + + r_resource_resgroup-62 + Resources + + + + r_computeResource_domain-c69 + PS2 + + r_host_host-859 + itdmdnvm-ps03.nd.gov + + + r_host_host-860 + itdmdnvm-ps04.nd.gov + + + r_host_host-866 + itdmdnvm-ps07.nd.gov + + + r_host_host-862 + itdmdnvm-ps06.nd.gov + + + r_host_host-865 + itdmdnvm-ps08.nd.gov + + + r_host_host-27493 + itdmdnvm-ps01.nd.gov + + + r_host_host-27497 + itdmdnvm-ps02.nd.gov + + + r_host_host-861 + itdmdnvm-ps05.nd.gov + + + r_resource_resgroup-70 + Resources + + + + r_computeResource_domain-c67 + ORACLE2 + + r_host_host-1126 + itdappvm251.nd.gov + + + r_resource_resgroup-68 + Resources + + + + r_computeResource_domain-c71 + SQL2 + + r_host_host-1134 + itdappvm204.nd.gov + + + r_host_host-1578 + itdmdnvm-sql04.nd.gov + + + r_host_host-1258 + itdappvm206.nd.gov + + + r_host_host-1285 + itdappvm207.nd.gov + + + r_host_host-1579 + itdmdnvm-sql05.nd.gov + + + r_host_host-1561 + itdmdnvm-sql01.nd.gov + + + r_host_host-1192 + itdappvm205.nd.gov + + + r_resource_resgroup-72 + Resources + + + + r_computeResource_domain-c75 + TEL2 + + r_host_host-31194 + itdmdnvm-tel04.nd.gov + + + r_host_host-1094 + itdmdnvm-tel03.nd.gov + + + r_host_host-1108 + itdmdnvm-tel02.nd.gov + + + r_host_host-31191 + itdmdnvm-tel05.nd.gov + + + r_host_host-1118 + itdmdnvm-tel01.nd.gov + + + r_resource_resgroup-76 + Resources + + + + r_computeResource_domain-c73 + SQL2-DR + + r_host_host-1453 + itdmdnvm-sql03.nd.gov + + + r_host_host-1464 + itdmdnvm-sql06.nd.gov + + + r_host_host-1440 + itdmdnvm-sql02.nd.gov + + + r_resource_resgroup-74 + Resources + + + + r_computeResource_domain-c77 + WAS2 + + r_host_host-23910 + itdmdnvm-was01.nd.gov + + + r_host_host-1168 + itdmdnvm-was03.nd.gov + + + r_host_host-1208 + itdmdnvm-was02.nd.gov + + + r_host_host-5488 + itdmdnvm-was04.nd.gov + + + r_resource_resgroup-78 + Resources + + + + + r_network_dvportgroup-350 + dvPG_4078_10.2.106.64_28 + + + r_network_dvportgroup-382 + dvPG_3856_10.2.97.0_28 + + + r_network_dvportgroup-353 + dvPG_4081_10.2.106.112_28 + + + r_network_dvportgroup-19229 + dvPG_3962_10.2.123.176_28 + + + r_network_dvportgroup-593 + dvPG_3664_10.2.12.224_28 + + + r_network_dvportgroup-25459 + dvPG_3706_10.8.139.248_29 + + + r_network_dvportgroup-11041 + dvPG_1999_10.2.120.208_28 + + + r_network_dvportgroup-25458 + dvPG_3705_10.8.139.240_29 + + + r_network_dvportgroup-25335 + dvPG_3996_10.2.164.32_28 + + + r_network_dvportgroup-327 + dvPG_1803_10.2.112.192_28 + + + r_network_dvportgroup-325 + dvPG_3932_10.2.97.80_28 + + + r_network_dvportgroup-17739 + dvPG_1910_10.221.10.160_28 + + + r_network_dvportgroup-330 + dvPG_1801_10.2.112.160_28 + + + r_network_dvportgroup-328 + dvPG_4039_10.2.100.96_28 + + + r_network_dvportgroup-25246 + dvPG_3596_10.2.163.208_28 + + + r_network_dvportgroup-355 + dvPG_4079_10.2.106.80_28 + + + r_network_dvportgroup-319 + dvPG_4045_10.2.100.192_28 + + + r_network_dvportgroup-29441 + dvPG_1839_10.2.114.128_28 + + + r_network_dvportgroup-635 + dvPG_3704_10.8.34.240_28 + + + r_network_dvportgroup-217 + dvPG_3634_10.2.135.0_30 + + + r_network_dvportgroup-298 + dvPG_0251_10.2.107.80_28 + + + r_network_dvportgroup-18847 + dvPG_3321_10.2.151.192_28 + + + r_network_dvportgroup-307 + dvPG_3861_10.2.95.224_28 + + + r_network_dvportgroup-21857 + dvPG_2222_1.2.3.4_11 + + + r_network_dvportgroup-24535 + dvPG_3362_10.8.137.168_29 + + + r_network_dvportgroup-17752 + dvPG_1858_10.221.7.192_28 + + + r_network_dvportgroup-24530 + dvPG_3348_10.2.163.48_28 + + + r_network_dvportgroup-24442 + dvPG_1840_10.2.162.160_28 + + + r_network_dvportgroup-22650 + dvPG_2486_10.2.162.224_28 + + + r_network_dvportgroup-8581 + dvPG_1955_10.2.120.64_28 + + + r_network_dvportgroup-22888 + dvPG_1340_10.2.162.240_28 + + + r_network_dvportgroup-741 + dvPG_SDC_TEL_VMOTION + + + r_network_dvportgroup-22324 + dvPG_3890_10.2.162.48_28 + + + r_network_dvportgroup-30403 + dvPG_2281_10.2.152.176_28 + + + r_network_dvportgroup-20326 + dvPG_3317_10.2.161.144_28 + + + r_network_dvportgroup-20325 + dvPG_3318_10.2.161.176_28 + + + r_network_dvportgroup-304 + dvPG_1807_10.2.112.208_28 + + + r_network_dvportgroup-380 + dvPG_4025_10.2.99.192_28 + + + r_network_dvportgroup-18878 + dvPG_3669_10.2.160.128_28 + + + r_network_dvportgroup-305 + dvPG_1808_10.2.112.224_28 + + + r_network_dvportgroup-703 + dvPG_3726_10.2.82.80_28 + + + r_network_dvportgroup-11483 + dvPG_3425_10.2.121.176_28 + + + r_network_dvportgroup-30402 + dvPG_2280_10.2.152.160_28 + + + r_network_dvportgroup-627 + dvPG_2471_10.8.139.224_29 + + + r_network_dvportgroup-17748 + dvPG_1854_10.221.7.128_28 + + + r_network_dvportgroup-24528 + dvPG_3357_10.8.137.128_29 + + + r_network_dvportgroup-17721 + dvPG_1881_10.221.8.240_28 + + + r_network_dvportgroup-275 + dvPG_1891_10.221.9.128_27 + + + r_network_dvportgroup-212 + dvPG_3756_10.2.86.80_28 + + + r_network_dvportgroup-19708 + dvPG_3514_10.8.137.112_29 + + + r_network_dvportgroup-19476 + dvPG_3327_10.2.161.0_28 + + + r_network_dvportgroup-19419 + dvPG_3325_10.2.160.224_28 + + + r_network_dvportgroup-25027 + dvPG_3450_10.2.163.96_28 + + + r_network_dvportgroup-26896 + dvPG_3866_10.2.123.208_28 + + + r_network_dvportgroup-259 + dvPG_4057_10.2.101.144_28 + + + r_network_dvportgroup-22649 + dvPG_2485_10.2.162.192_28 + + + r_network_dvportgroup-288 + dvPG_1837_10.2.114.96_28 + + + r_network_dvportgroup-272 + dvPG_1703_10.2.107.32_28 + + + r_network_dvportgroup-27591 + dvPG_114_10.2.114.240_28 + + + r_network_dvportgroup-18659 + dvPG_0726_10.8.154.192_29 + + + r_network_dvportgroup-633 + dvPG_1745_10.2.109.224_28 + + + r_network_dvportgroup-25813 + dvPG_3820_10.2.93.64_28 + + + r_network_dvportgroup-18848 + dvPG_3322_10.2.160.192_28 + + + r_network_dvportgroup-411 + dvPG_3686_10.2.80.16_28 + + + r_network_dvportgroup-16322 + dvPG_3971_10.2.152.0_27 + + + r_network_dvportgroup-417 + dvPG_0736_10.8.153.192_26 + + + r_network_dvportgroup-22031 + dvPG_3351_10.2.162.112_28 + + + r_network_dvportgroup-17725 + dvPG_1887_10.221.9.80_28 + + + r_network_dvportgroup-17788 + dvPG_3449_10.2.151.160_28 + + + r_network_dvportgroup-528 + dvPG_1725_10.2.108.96_28 + + + r_network_dvportgroup-257 + dvPG_1733_10.2.108.224_28 + + + r_network_dvportgroup-28641 + dvPG_1105_10.2.166.80_28 + + + r_network_dvportgroup-252 + dvPG_4011_10.2.99.0_28 + + + r_network_dvportgroup-517 + dvPG_1876_10.221.8.160_28 + + + r_network_dvportgroup-279 + dvPG_1704_10.2.107.48_28 + + + r_network_dvportgroup-248 + dvPG_4051_10.2.101.48_28 + + + r_network_dvportgroup-17756 + dvPG_1862_10.221.8.0_28 + + + r_network_dvportgroup-17753 + dvPG_1859_10.221.7.208_28 + + + r_network_dvportgroup-17751 + dvPG_1857_10.221.7.176_28 + + + r_network_dvportgroup-324 + dvPG_4046_10.2.100.208_28 + + + r_network_dvportgroup-18115 + dvPG_3500_10.2.123.80_28 + + + r_network_dvportgroup-266 + dvPG_4052_10.2.101.64_28 + + + r_network_dvportgroup-200 + dvPG_4070_10.2.101.192_28 + + + r_network_dvportgroup-436 + dvPG_3652_10.2.12.32_28 + + + r_network_dvportgroup-18301 + dvPG_1845_10.2.114.192_28 + + + r_network_dvportgroup-497 + dvPG_3697_10.2.80.192_28 + + + r_network_dvportgroup-251 + dvPG_1771_10.2.111.64_28 + + + r_network_dvportgroup-689 + dvPG_0174_165.234.112.0_29 + + + r_network_dvportgroup-292 + dvPG_1902_10.221.10.64_28 + + + r_network_dvportgroup-11338 + dvPG_3428_10.2.121.208_28 + + + r_network_dvportgroup-192 + dvPG_3771_10.34.77.24_29 + + + r_network_dvportgroup-18064 + dvPG_3521_10.2.123.96_28 + + + r_network_dvportgroup-11475 + dvPG_3417_10.2.121.48_28 + + + r_network_dvportgroup-3283 + dvPG_1933_10.2.115.160_28 + + + r_network_dvportgroup-12784 + dvPG_3431_10.2.122.48_28 + + + r_network_dvportgroup-13934 + dvPG_3438_10.2.122.144_28 + + + r_network_dvportgroup-8092 + dvPG_1990_10.2.120.0_28 + + + r_network_dvportgroup-386 + dvPG_3789_10.2.84.144_28 + + + r_network_dvportgroup-19420 + dvPG_3326_10.2.160.240_28 + + + r_network_dvportgroup-26370 + dvPG_3707_10.2.93.96_28 + + + r_network_dvportgroup-441 + dvPG_0259_10.2.39.0_24 + + + r_network_dvportgroup-26742 + dvPG_3830_10.2.22.0_26 + + + r_network_dvportgroup-419 + dvPG_3790_10.2.84.160_28 + + + r_network_dvportgroup-18300 + dvPG_3426_10.2.122.0_28 + + + r_network_dvportgroup-219 + dvPG_3797_10.2.84.208_28 + + + r_network_dvportgroup-26094 + dvPG_3713_10.2.165.0_28 + + + r_network_dvportgroup-16286 + dvPG_0045_10.2.8.0_24_Custom + + + r_network_dvportgroup-25457 + dvPG_3361_10.8.137.160_29 + + + r_network_dvportgroup-295 + dvPG_1901_10.221.10.0_26 + + + r_network_dvportgroup-264 + dvPG_4054_10.2.101.96_28 + + + r_network_dvportgroup-178 + dvPG_3699_10.2.13.16_28 + + + r_network_dvportgroup-731 + dvPG_4036_10.2.24.0_24 + + + r_network_dvportgroup-20327 + dvPG_3334_10.2.161.192_28 + + + r_network_dvportgroup-17727 + dvPG_1892_10.221.9.160_27 + + + r_network_dvportgroup-17746 + dvPG_1852_10.221.7.96_28 + + + r_network_dvportgroup-296 + dvPG_1789_10.2.150.64_26 + + + r_network_dvportgroup-397 + dvPG_1765_10.2.110.224_28 + + + r_network_dvportgroup-614 + dvPG_2321_10.8.139.160_27 + + + r_network_dvportgroup-16290 + dvPG_3980_10.2.151.32_28 + + + r_network_dvportgroup-23911 + dvPG_1351_10.2.163.32_28 + + + r_network_dvportgroup-249 + dvPG_1770_10.2.111.48_28 + + + r_network_dvportgroup-310 + dvPG_1714_10.2.107.176_28 + + + r_network_dvportgroup-25812 + dvPG_3819_10.2.93.48_28 + + + r_network_dvportgroup-339 + dvPG_4001_10.2.98.144_28 + + + r_network_dvportgroup-17716 + dvPG_1867_10.221.8.80_28 + + + r_network_dvportgroup-20895 + dvPG_3507_10.2.162.0_28 + + + r_network_dvportgroup-678 + dvPG_3725_10.2.82.64_28 + + + r_network_dvportgroup-17717 + dvPG_1868_10.221.8.96_28 + + + r_network_dvportgroup-17337 + dvPG_0184_10.2.160.96_28 + + + r_network_dvportgroup-361 + dvPG_1824_10.2.113.224_28 + + + r_network_dvportgroup-207 + dvPG_2476_10.8.71.0_28 + + + r_network_dvportgroup-28386 + dvPG_3313_10.2.165.48_28 + + + r_network_dvportgroup-19796 + dvPG_3329_10.2.161.80_28 + + + r_network_dvportgroup-479 + dvPG_0133_10.2.135.248_29 + + + r_network_dvportgroup-303 + dvPG_1769_10.2.111.32_28 + + + r_network_dvportgroup-246 + dvPG_4049_10.2.101.16_28 + + + r_network_dvportgroup-17755 + dvPG_1861_10.221.7.240_28 + + + r_network_dvportgroup-16293 + dvPG_3983_10.2.151.80_28 + + + r_network_dvportgroup-17758 + dvPG_1864_10.221.8.32_28 + + + r_network_dvportgroup-17715 + dvPG_1866_10.221.8.64_28 + + + r_network_dvportgroup-16291 + dvPG_3981_10.2.151.48_28 + + + r_network_dvportgroup-11472 + dvPG_3414_10.2.121.0_28 + + + r_network_dvportgroup-19478 + dvPG_0140_10.2.152.144_28 + + + r_network_dvportgroup-211 + dvPG_3823_10.2.95.16_28 + + + r_network_dvportgroup-16294 + dvPG_3984_10.2.151.112_28 + + + r_network_dvportgroup-25028 + dvPG_3451_10.2.163.112_28 + + + r_network_dvportgroup-168 + dvPG_SDC_MGMT + + + r_network_dvportgroup-14517 + dvPG_3441_10.2.122.192_28 + + + r_network_dvportgroup-306 + dvPG_1787_10.2.112.32_28 + + + r_network_dvportgroup-348 + dvPG_1717_10.2.107.224_28 + + + r_network_dvportgroup-17723 + dvPG_1885_10.221.9.48_28 + + + r_network_dvportgroup-16287 + dvPG_3839_10.2.85.128_28 + + + r_network_dvportgroup-574 + dvPG_2402_10.2.133.64_26 + + + r_network_dvportgroup-28640 + dvPG_1104_10.2.166.64_28 + + + r_network_dvportgroup-16292 + dvPG_3982_10.2.151.64_28 + + + r_network_dvportgroup-331 + dvPG_1802_10.2.112.176_28 + + + r_network_dvportgroup-235 + dvPG_1792_10.2.112.48_28 + + + r_network_dvportgroup-490 + dvPG_1742_10.2.109.48_28 + + + r_network_dvportgroup-425 + dvPG_3939_10.57.66.224_27 + + + r_network_dvportgroup-16323 + dvPG_3972_10.2.152.32_27 + + + r_network_dvportgroup-25247 + dvPG_3597_10.2.163.224_28 + + + r_network_dvportgroup-18299 + dvPG_3589_10.2.151.128_28 + + + r_network_dvportgroup-12956 + dvPG_3432_10.2.122.64_28 + + + r_network_dvportgroup-20896 + dvPG_3508_10.2.162.16_28 + + + r_network_dvportgroup-22119 + dvPG_3985_10.2.162.176_28 + + + r_network_dvportgroup-464 + dvPG_0076_10.221.6.0_24 + + + r_network_dvportgroup-209 + dvPG_3826_10.2.84.240_28 + + + r_network_dvportgroup-203 + dvPG_3944_10.2.81.144_28 + + + r_network_dvportgroup-17718 + dvPG_1870_10.221.8.128_28 + + + r_network_dvportgroup-573 + dvPG_3695_10.2.80.160_28 + + + r_network_dvportgroup-11473 + dvPG_3415_10.2.121.16_28 + + + r_network_dvportgroup-19202 + dvPG_3961_10.2.123.160_28 + + + r_network_dvportgroup-28214 + dvPG_3510_10.2.165.32_28 + + + r_network_dvportgroup-459 + dvPG_1779_10.2.149.0_27 + + + r_network_dvportgroup-648 + dvPG_1145_10.2.6.0_24 + + + r_network_dvportgroup-255 + dvPG_1732_10.2.108.208_28 + + + r_network_dvportgroup-11478 + dvPG_3420_10.2.121.96_28 + + + r_network_dvportgroup-31257 + dvPG_701_10.2.103.112_28 + + + r_network_dvportgroup-301 + dvPG_1905_10.221.10.80_28 + + + r_network_dvportgroup-8408 + dvPG_1984_10.2.120.32_28 + + + r_network_dvportgroup-6128 + dvPG_4075_10.2.101.208_28 + + + r_network_dvportgroup-343 + dvPG_4068_10.2.106.32_28 + + + r_network_dvportgroup-228 + dvPG_0176_10.2.140.16_28 + + + r_network_dvportgroup-332 + dvPG_1785_10.2.112.0_28 + + + r_network_dvportgroup-16326 + dvPG_3974_10.2.152.96_27 + + + r_network_dvportgroup-17364 + dvPG_3421_10.2.121.112_28 + + + r_network_dvportgroup-352 + dvPG_4069_10.2.106.48_28 + + + r_network_dvportgroup-400 + dvPG_4092_10.2.103.24_29 + + + r_network_dvportgroup-693 + dvPG_1757_10.2.110.112_28 + + + r_network_dvportgroup-20925 + dvPG_3509_10.2.161.240_28 + + + r_network_dvportgroup-682 + dvPG_1826_10.2.114.0_28 + + + r_network_dvportgroup-25245 + dvPG_3595_10.2.163.192_28 + + + r_network_dvportgroup-213 + dvPG_3757_10.2.86.96_28 + + + r_network_dvportgroup-221 + dvPG_2469_10.34.154.32_28 + + + r_network_dvportgroup-599 + dvPG_0002_10.2.2.0_23 + + + r_network_dvportgroup-26894 + dvPG_2002_10.2.166.32_28 + + + r_network_dvportgroup-30883 + dvPG_2005_10.2.165.96_28 + + + r_network_dvportgroup-594 + dvPG_3730_10.2.82.144_28 + + + r_network_dvportgroup-24529 + dvPG_3359_10.8.137.144_29 + + + r_network_dvportgroup-17750 + dvPG_1856_10.221.7.160_28 + + + r_network_dvportgroup-194 + dvPG_3770_10.2.81.224_28 + + + r_network_dvportgroup-10394 + dvPG_1848_10.2.115.0_28 + + + r_network_dvportgroup-11476 + dvPG_3418_10.2.121.64_28 + + + r_network_dvportgroup-364 + dvPG_1720_10.2.108.16_28 + + + r_network_dvportgroup-17741 + dvPG_1912_10.221.10.192_28 + + + r_network_dvportgroup-281 + dvPG_4005_10.2.140.144_28 + + + r_network_dvportgroup-575 + dvPG_3694_10.2.80.144_28 + + + r_network_dvportgroup-10106 + dvPG_0608_10.2.120.176_28 + + + r_network_dvportgroup-15890 + dvPG_3446_10.2.123.16_28 + + + r_network_dvportgroup-318 + dvPG_1793_10.2.112.64_28 + + + r_network_dvportgroup-529 + dvPG_1869_10.221.8.112_28 + + + r_network_dvportgroup-183 + dvPG_4084_10.2.106.128_28 + + + r_network_dvportgroup-507 + dvPG_1872_10.221.11.0_27 + + + r_network_dvportgroup-229 + dvPG_0175_10.2.140.0_28 + + + r_network_dvportgroup-24254 + dvPG_1064_10.2.161.160_28 + + + r_network_dvportgroup-342 + dvPG_4004_10.2.98.192_28 + + + r_network_dvportgroup-19418 + dvPG_3324_10.2.151.240_28 + + + r_network_dvportgroup-644 + dvPG_1395_10.8.154.0_26 + + + r_network_dvportgroup-561 + dvPG_3688_10.2.80.48_28 + + + r_network_dvportgroup-345 + dvPG_4066_10.2.106.0_28 + + + r_network_dvportgroup-360 + dvPG_1776_10.2.111.144_28 + + + r_network_dvportgroup-525 + dvPG_1726_10.2.108.112_28 + + + r_network_dvportgroup-17745 + dvPG_1851_10.221.7.80_28 + + + r_network_dvportgroup-359 + dvPG_1721_10.2.108.32_28 + + + r_network_dvportgroup-391 + dvPG_3802_10.2.92.32_28 + + + r_network_dvportgroup-24671 + dvPG_3413_10.2.163.80_28 + + + r_network_dvportgroup-283 + dvPG_1702_10.2.107.16_28 + + + r_network_dvportgroup-673 + dvPG_3736_10.2.88.0_24 + + + r_network_dvportgroup-17737 + dvPG_1908_10.221.10.128_28 + + + r_network_dvportgroup-363 + dvPG_1825_10.2.113.240_28 + + + r_network_dvportgroup-650 + dvPG_0036_10.2.29.0_24 + + + r_network_dvportgroup-356 + dvPG_3934_10.2.97.176_28 + + + r_network_dvportgroup-447 + dvPG_3937_10.2.98.96_28 + + + r_network_dvportgroup-706 + dvPG_3727_10.2.82.96_28 + + + r_network_dvportgroup-27010 + dvPG_3683_10.2.93.144_28 + + + r_network_dvportgroup-555 + dvPG_4072_10.2.81.192_28 + + + r_network_dvportgroup-401 + dvPG_1791_10.2.111.240_28 + + + r_network_dvportgroup-383 + dvPG_3850_10.2.95.144_28 + + + r_network_dvportgroup-483 + dvPG_1738_10.2.109.32_28 + + + r_network_dvportgroup-370 + dvPG_0097_10.2.138.0_26 + + + r_network_dvportgroup-26748 + dvPG_2278_165.234.164.0_27 + + + r_network_dvportgroup-432 + dvPG_4026_10.2.99.208_28 + + + r_network_dvportgroup-175 + dvPG_1820_10.2.149.64_27 + + + r_network_dvportgroup-17736 + dvPG_1907_10.221.10.112_28 + + + r_network_dvportgroup-482 + dvPG_4047_10.2.100.224_28 + + + r_network_dvportgroup-634 + dvPG_2347_10.8.34.96_27 + + + r_network_dvportgroup-444 + dvPG_1782_10.2.111.176_28 + + + r_network_dvportgroup-11201 + dvPG_4071_10.2.120.224_28 + + + r_network_dvportgroup-654 + dvPG_3715_10.2.81.64_28 + + + r_network_dvportgroup-475 + dvPG_3692_10.2.80.112_28 + + + r_network_dvportgroup-4068 + dvPG_1952_10.2.118.176_28 + + + r_network_dvportgroup-378 + dvPG_4023_10.2.99.160_28 + + + r_network_dvportgroup-647 + dvPG-ITDINTLB-INT-TRNK + + + r_network_dvportgroup-300 + dvPG_1906_10.221.10.96_28 + + + r_network_dvportgroup-313 + dvPG_1832_10.2.114.48_28 + + + r_network_dvportgroup-429 + dvPG_0543_165.234.136.0_24_Data + + + r_network_dvportgroup-19447 + dvPG_0155_10.2.152.128_28 + + + r_network_dvportgroup-466 + dvPG_1884_10.221.9.32_28 + + + r_network_dvportgroup-28698 + dvPG_1186_10.2.72.0_23 + + + r_network_dvportgroup-392 + dvPG_1735_10.2.109.0_28 + + + r_network_dvportgroup-394 + dvPG_1736_10.2.109.16_28 + + + r_network_dvportgroup-398 + dvPG_1753_10.2.110.48_28 + + + r_network_dvportgroup-31345 + dvPG_0703_10.2.166.128_28 + + + r_network_dvportgroup-237 + dvPG_1914_10.221.10.224_28 + + + r_network_dvportgroup-12953 + dvPG_3435_10.2.122.112_28 + + + r_network_dvportgroup-413 + dvPG_3687_10.2.80.32_28 + + + r_network_dvportgroup-426 + dvPG_0007_10.2.9.0_24 + + + r_network_dvportgroup-550 + dvPG_1829_10.8.137.96_29 + + + r_network_dvportgroup-428 + dvPG_3660_10.2.12.160_28 + + + r_network_dvportgroup-210 + dvPG_3662_10.2.12.192_28 + + + r_network_dvportgroup-699 + dvPG_2389_10.8.154.240_29 + + + r_network_dvportgroup-454 + dvPG_3859_10.2.97.48_28 + + + r_network_dvportgroup-387 + dvPG_3841_10.2.95.128_28 + + + r_network_dvportgroup-430 + dvPG_2345_10.8.34.32_27 + + + r_network_dvportgroup-18877 + dvPG_1983_10.2.160.144_28 + + + r_network_dvportgroup-451 + dvPG_3883_10.2.98.16_28 + + + r_network_dvportgroup-700 + dvPG_3724_10.2.82.48_28 + + + r_network_dvportgroup-438 + dvPG_3653_10.2.12.48_28 + + + r_network_dvportgroup-25208 + dvPG_4030_10.2.164.16_28 + + + r_network_dvportgroup-28699 + dvPG_1187_10.2.76.0_22 + + + r_network_dvportgroup-587 + dvPG_2322_10.8.139.192_27 + + + r_network_dvportgroup-202 + dvPG_4014_10.2.81.176_28 + + + r_network_dvportgroup-369 + dvPG_4091_10.8.137.80_28 + + + r_network_dvportgroup-457 + dvPG_1777_10.2.138.64_26 + + + r_network_dvportgroup-247 + dvPG_4050_10.2.101.32_28 + + + r_network_dvportgroup-340 + dvPG_4002_10.2.98.160_28 + + + r_network_dvportgroup-608 + dvPG_0263_10.2.37.0_24 + + + r_network_dvportgroup-493 + dvPG_1878_10.221.8.192_28 + + + r_network_dvportgroup-591 + dvPG_3778_10.2.84.112_28 + + + r_network_dvportgroup-263 + dvPG_4055_10.2.101.112_28 + + + r_network_dvportgroup-581 + dvPG_3838_10.2.95.112_28 + + + r_network_dvportgroup-388 + dvPG_3943_10.2.98.64_28 + + + r_network_dvportgroup-622 + dvPG_3810_10.2.92.160_28 + + + r_network_dvportgroup-465 + dvPG_4087_10.2.103.16_29 + + + r_network_dvportgroup-341 + dvPG_4003_10.2.98.176_28 + + + r_network_dvportgroup-302 + dvPG_1904_10.221.11.160_27 + + + r_network_dvportgroup-12952 + dvPG_3433_10.2.122.80_28 + + + r_network_dvportgroup-412 + dvPG_3709_10.2.80.224_28 + + + r_network_dvportgroup-434 + dvPG_3651_10.2.12.16_28 + + + r_network_dvportgroup-680 + dvPG_1760_10.2.110.160_28 + + + r_network_dvportgroup-567 + dvPG_3693_10.2.80.128_28 + + + r_network_dvportgroup-19201 + dvPG_3960_10.2.123.144_28 + + + r_network_dvportgroup-25240 + dvPG_3598_10.2.163.240_28 + + + r_network_dvportgroup-486 + dvPG_3999_10.2.109.80_28 + + + r_network_dvportgroup-615 + dvPG_3807_10.2.92.112_28 + + + r_network_dvportgroup-365 + dvPG_4062_10.2.105.0_24 + + + r_network_dvportgroup-606 + dvPG_3772_10.2.84.32_28 + + + r_network_dvportgroup-320 + dvPG_4044_10.2.100.176_28 + + + r_network_dvportgroup-362 + dvPG_1774_10.2.111.112_28 + + + r_network_dvportgroup-461 + dvPG_1882_10.221.9.0_28 + + + r_network_dvportgroup-385 + dvPG_3800_10.2.92.0_28 + + + r_network_dvportgroup-527 + dvPG_3711_10.2.81.0_28 + + + r_network_dvportgroup-329 + dvPG_1800_10.2.112.144_28 + + + r_network_dvportgroup-476 + dvPG_1767_10.2.111.16_28 + + + r_network_dvportgroup-652 + dvPG_3716_10.2.81.80_28 + + + r_network_dvportgroup-389 + dvPG_3801_10.2.92.16_28 + + + r_network_dvportgroup-686 + dvPG_0746_10.8.139.96_27 + + + r_network_dvportgroup-416 + dvPG_2405_10.2.134.0_26 + + + r_network_dvportgroup-17366 + dvPG_3423_10.2.121.144_28 + + + r_network_dvportgroup-14519 + dvPG_3443_10.2.122.224_28 + + + r_network_dvportgroup-494 + dvPG_0743_10.8.139.32_27 + + + r_network_dvportgroup-657 + dvPG_1731_10.2.108.192_28 + + + r_network_dvportgroup-17754 + dvPG_1860_10.221.7.224_28 + + + r_network_dvportgroup-30508 + dvPG_2004_10.2.163.8_29 + + + r_network_dvportgroup-233 + dvPG_1805_10.2.113.0_28 + + + r_network_dvportgroup-30482 + dvPG_1922_10.2.166.112_28 + + + r_network_dvportgroup-452 + dvPG_3884_10.2.98.32_28 + + + r_network_dvportgroup-225 + dvPG_2459_10.34.154.0_28 + + + r_network_dvportgroup-245 + dvPG_4048_10.2.101.0_28 + + + r_network_dvportgroup-534 + dvPG_1727_10.2.108.128_28 + + + r_network_dvportgroup-322 + dvPG_1709_10.2.14.16_28 + + + r_network_dvportgroup-616 + dvPG_3728_10.2.82.112_28 + + + r_network_dvportgroup-10105 + dvPG_0607_10.2.120.160_28 + + + r_network_dvportgroup-204 + dvPG_2404_10.2.133.192_26 + + + r_network_dvportgroup-408 + dvPG_4065_10.2.101.176_28 + + + r_network_dvportgroup-278 + dvPG_1705_10.2.107.64_28 + + + r_network_dvportgroup-453 + dvPG_3885_10.2.98.48_28 + + + r_network_dvportgroup-690 + dvPG_3666_165.234.44.48_28 + + + r_network_dvportgroup-510 + dvPG_1877_10.221.8.176_28 + + + r_network_dvportgroup-26746 + dvPG_2430_10.2.20.0_24_AVAYA + + + r_network_dvportgroup-17726 + dvPG_1889_10.221.9.112_28 + + + r_network_dvportgroup-675 + dvPG_3721_10.2.82.0_28 + + + r_network_dvportgroup-223 + dvPG_2458_10.2.10.16_29 + + + r_network_dvportgroup-663 + dvPG_2341_10.2.64.0_24 + + + r_network_dvportgroup-13983 + dvPG_3439_10.2.122.160_28 + + + r_network_dvportgroup-643 + dvPG_3717_10.2.81.96_28 + + + r_network_dvportgroup-613 + dvPG_3804_10.2.92.64_28 + + + r_network_dvportgroup-462 + dvPG_0728_10.8.153.128_26 + + + r_network_dvportgroup-694 + dvPG_1756_10.2.110.96_28 + + + r_network_dvportgroup-22831 + dvPG_0102_10.2.163.0_29 + + + r_network_dvportgroup-8225 + dvPG_1958_10.2.120.16_28 + + + r_network_dvportgroup-176 + dvPG_3655_10.2.12.80_28 + + + r_network_dvportgroup-358 + dvPG_1707_10.2.107.112_28 + + + r_network_dvportgroup-531 + dvPG_3842_10.2.96.0_25 + + + r_network_dvportgroup-14520 + dvPG_3444_10.2.122.240_28 + + + r_network_dvportgroup-670 + dvPG_3714_10.2.81.48_28 + + + r_network_dvportgroup-335 + dvPG_3864_10.2.97.224_28 + + + r_network_dvportgroup-445 + dvPG_1783_10.2.111.192_28 + + + r_network_dvportgroup-27527 + dvPG_3000_10.2.123.224_28 + + + r_network_dvportgroup-22030 + dvPG_3350_10.2.162.96_28 + + + r_network_dvportgroup-431 + dvPG_3710_10.2.80.240_28 + + + r_network_dvportgroup-18302 + dvPG_3427_10.2.122.16_28 + + + r_network_dvportgroup-366 + dvPG_1823_10.2.113.208_28 + + + r_network_dvportgroup-27592 + dvPG_119_10.2.121.240_28 + + + r_network_dvportgroup-515 + dvPG_1875_10.221.11.96_27 + + + r_network_dvportgroup-17742 + dvPG_1913_10.221.10.208_28 + + + r_network_dvportgroup-24256 + dvPG_3356_10.8.137.120_29 + + + r_network_dvportgroup-15889 + dvPG_3445_10.2.123.0_28 + + + r_network_dvportgroup-6208 + dvPG_1963_10.2.119.16_28 + + + r_network_dvportgroup-621 + dvPG_3811_10.2.92.176_28 + + + r_network_dvportgroup-704 + dvPG_4007_10.2.140.176_28 + + + r_network_dvportgroup-420 + dvPG_2406_10.2.134.64_26 + + + r_network_dvportgroup-25241 + dvPG_3591_10.2.163.128_28 + + + r_network_dvportgroup-311 + dvPG_1812_10.2.113.64_28 + + + r_network_dvportgroup-321 + dvPG_1710_10.2.14.0_28 + + + r_network_dvportgroup-696 + dvPG_1755_10.2.110.80_28 + + + r_network_dvportgroup-446 + dvPG_1784_10.2.111.208_28 + + + r_network_dvportgroup-28937 + dvPG_203_10.2.0.16_28 + + + r_network_dvportgroup-26373 + dvPG_2001_10.2.166.16_28 + + + r_network_dvportgroup-583 + dvPG_2477_10.8.71.16_28 + + + r_network_dvportgroup-684 + dvPG_1759_10.2.110.144_28 + + + r_network_dvportgroup-661 + dvPG_2399_10.2.132.128_26 + + + r_network_dvportgroup-7835 + dvPG_1986_10.2.119.176_28 + + + r_network_dvportgroup-487 + dvPG_1739_10.2.109.144_28 + + + r_network_dvportgroup-491 + dvPG_1879_10.221.8.208_28 + + + r_network_dvportgroup-25209 + dvPG_4029_10.2.164.0_28 + + + r_network_dvportgroup-577 + dvPG_3908_10.2.98.240_28 + + + r_network_dvportgroup-702 + dvPG_3712_10.2.81.16_28 + + + r_network_dvportgroup-499 + dvPG_0200_10.2.16.0_23 + + + r_network_dvportgroup-30681 + dvPG_1923_10.2.165.64_28 + + + r_network_dvportgroup-649 + dvPG_0258_10.2.42.0_24 + + + r_network_dvportgroup-601 + dvPG_2394_10.2.66.0_24 + + + r_network_dvportgroup-641 + dvPG_2350_10.8.34.192_28 + + + r_network_dvportgroup-6742 + dvPG_1965_10.2.119.48_28 + + + r_network_dvportgroup-513 + dvPG_0262_10.2.36.0_24 + + + r_network_dvportgroup-357 + dvPG_3933_10.2.97.160_28 + + + r_network_dvportgroup-17747 + dvPG_1853_10.221.7.112_28 + + + r_network_dvportgroup-590 + dvPG_3731_10.2.82.160_28 + + + r_network_dvportgroup-27526 + dvPG_3001_10.2.115.240_28 + + + r_network_dvportgroup-617 + dvPG_3806_10.2.92.96_28 + + + r_network_dvportgroup-480 + dvPG_4089_10.2.106.192_28 + + + r_network_dvportgroup-24670 + dvPG_3412_10.2.163.64_28 + + + r_network_dvportgroup-481 + dvPG_3754_10.2.98.80_28 + + + r_network_dvportgroup-25334 + dvPG_3997_10.2.164.48_28 + + + r_network_dvportgroup-21858 + dvPG_3889_10.2.162.32_28 + + + r_network_dvportgroup-645 + dvPG-ITDINTLB-EXT-TRNK + + + r_network_dvportgroup-187 + dvPG_3737_10.2.84.0_28 + + + r_network_dvportgroup-724 + dvPG_SDC_AVAYA_MGMT + + + r_network_dvportgroup-674 + dvPG_0737_165.234.153.192_26 + + + r_network_dvportgroup-618 + dvPG_3809_10.2.92.144_28 + + + r_network_dvportgroup-646 + dvPG_0100_10.221.5.0_24 + + + r_network_dvportgroup-592 + dvPG_2467_10.8.154.128_26 + + + r_network_dvportgroup-536 + dvPG_1723_10.2.108.64_28 + + + r_network_dvportgroup-687 + dvPG_3658_10.2.12.128_28 + + + r_network_dvportgroup-450 + dvPG_3882_10.2.98.0_28 + + + r_network_dvportgroup-679 + dvPG_3723_10.2.82.32_28 + + + r_network_dvportgroup-208 + dvPG_2479_10.8.71.48_28 + + + r_network_dvportgroup-502 + dvPG_1751_10.2.110.16_28 + + + r_network_dvportgroup-20328 + dvPG_3335_10.2.161.224_28 + + + r_network_dvportgroup-30509 + dvPG_3402_10.2.163.16_29 + + + r_network_dvportgroup-17720 + dvPG_1880_10.221.8.224_28 + + + r_network_dvportgroup-554 + dvPG_3774_10.2.84.64_27 + + + r_network_dvportgroup-589 + dvPG_4033_10.2.100.48_28 + + + r_network_dvportgroup-271 + dvPG_1744_10.2.109.208_28 + + + r_network_dvportgroup-460 + dvPG_1778_10.2.138.128_26 + + + r_network_dvportgroup-184 + dvPG_4085_10.2.106.144_28 + + + r_network_dvportgroup-28938 + dvPG_2180_165.234.16.0_28 + + + r_network_dvportgroup-560 + dvPG_4073_10.2.81.208_28 + + + r_network_dvportgroup-508 + dvPG_3751_10.2.86.64_28 + + + r_network_dvportgroup-404 + dvPG_3855_10.2.95.240_28 + + + r_network_dvportgroup-269 + dvPG_1743_10.2.109.192_28 + + + r_network_dvportgroup-439 + dvPG_0709_165.234.156.0_22 + + + r_network_dvportgroup-604 + dvPG_3812_10.2.92.192_28 + + + r_network_dvportgroup-7667 + dvPG_1968_10.2.119.144_28 + + + r_network_dvportgroup-18065 + dvPG_0191_10.2.123.112_28 + + + r_network_dvportgroup-17743 + dvPG_1915_10.221.10.240_28 + + + r_network_dvportgroup-602 + dvPG_3813_10.2.92.208_28 + + + r_network_dvportgroup-8690 + dvPG_1991_10.2.120.80_28 + + + r_network_dvportgroup-376 + dvPG_3936_10.2.97.208_28 + + + r_network_dvportgroup-505 + dvPG_1396_10.8.154.64_26 + + + r_network_dvportgroup-308 + dvPG_1786_10.2.112.16_28 + + + r_network_dvportgroup-11474 + dvPG_3416_10.2.121.32_28 + + + r_network_dvportgroup-612 + dvPG_3729_10.2.82.128_28 + + + r_network_dvportgroup-683 + dvPG_1758_10.2.110.128_28 + + + r_network_dvportgroup-24252 + dvPG_1062_10.2.160.160_28 + + + r_network_dvportgroup-552 + dvPG_3685_10.2.80.0_28 + + + r_network_dvportgroup-688 + dvPG_0747_10.8.139.128_27 + + + r_network_dvportgroup-16324 + dvPG_3973_10.2.152.64_27 + + + r_network_dvportgroup-172 + dvPG_SDC_VMOTION + + + r_network_dvportgroup-500 + dvPG_4077_10.2.101.240_28 + + + r_network_dvportgroup-558 + dvPG_1762_10.2.110.192_28 + + + r_network_dvportgroup-25244 + dvPG_3594_10.2.163.176_28 + + + r_network_dvportgroup-603 + dvPG_0710_10.8.159.0_24 + + + r_network_dvportgroup-4071 + dvPG_1954_10.2.118.208_28 + + + r_network_dvportgroup-539 + dvPG_1865_10.221.8.48_28 + + + r_network_dvportgroup-639 + dvPG_2348_10.8.34.128_27 + + + r_network_dvportgroup-516 + dvPG_3843_10.2.96.128_25 + + + r_network_dvportgroup-503 + dvPG_1161_10.11.12.0_23 + + + r_network_dvportgroup-625 + dvPG_2472_10.8.139.232_29 + + + r_network_dvportgroup-511 + dvPG_0085_10.11.2.0_24 + + + r_network_dvportgroup-609 + dvPG_0194_10.59.60.0_24 + + + r_network_dvportgroup-24257 + dvPG_3358_10.8.137.136_29 + + + r_network_dvportgroup-578 + dvPG_3906_10.2.98.208_28 + + + r_network_dvportgroup-256 + dvPG_1799_10.2.112.128_28 + + + r_network_dvportgroup-24443 + dvPG_1841_10.2.162.208_28 + + + r_network_dvportgroup-6975 + dvPG_1961_10.2.118.224_28 + + + r_network_dvportgroup-640 + dvPG_2349_10.8.34.160_27 + + + r_network_dvportgroup-512 + dvPG_3845_10.2.85.160_28 + + + r_network_dvportgroup-293 + dvPG_1903_10.221.11.128_27 + + + r_network_dvportgroup-22029 + dvPG_3349_10.2.162.80_28 + + + r_network_dvportgroup-458 + dvPG_1780_10.2.149.32_27 + + + r_network_dvportgroup-485 + dvPG_1750_10.2.110.0_28 + + + r_network_dvportgroup-530 + dvPG_3689_10.2.80.64_28 + + + r_network_dvportgroup-267 + dvPG_4043_10.2.100.160_28 + + + r_network_dvportgroup-695 + dvPG_1766_10.2.110.240_28 + + + r_network_dvportgroup-666 + dvPG_2395_165.234.44.0_29 + + + r_network_dvportgroup-506 + dvPG_3847_10.2.85.192_28 + + + r_network_dvportgroup-188 + dvPG_3825_10.2.95.48_28 + + + r_network_dvportgroup-344 + dvPG_4067_10.2.106.16_28 + + + r_network_dvportgroup-477 + dvPG_0087_10.2.81.240_28 + + + r_network_dvportgroup-467 + dvPG_0744_10.8.139.64_27 + + + r_network_dvportgroup-265 + dvPG_4053_10.2.101.80_28 + + + r_network_dvportgroup-10395 + dvPG_1926_10.2.115.32_28 + + + r_network_dvportgroup-455 + dvPG_3860_10.2.86.208_28 + + + r_network_dvportgroup-17308 + dvPG_0181_10.2.160.80_28 + + + r_network_dvportgroup-381 + dvPG_3857_10.2.97.16_28 + + + r_network_dvportgroup-677 + dvPG_3722_10.2.82.16_28 + + + r_network_dvportgroup-857 + dvPG_1847_10.2.114.224_28 + + + r_network_dvportgroup-8946 + dvPG_1844_10.2.114.176_28 + + + r_network_dvportgroup-492 + dvPG_2393_10.2.32.0_24 + + + r_network_dvportgroup-26371 + dvPG_3708_10.2.93.112_28 + + + r_network_dvportgroup-484 + dvPG_3998_10.2.109.64_28 + + + r_network_dvportgroup-607 + dvPG_0117_10.221.4.0_24 + + + r_network_dvportgroup-415 + dvPG_4060_10.2.100.240_28 + + + r_network_dvportgroup-12249 + dvPG_3430_10.2.122.32_28 + + + r_network_dvportgroup-509 + dvPG_3846_10.2.85.176_28 + + + r_network_dvportgroup-523 + dvPG_1730_10.2.108.176_28 + + + r_network_dvportgroup-488 + dvPG_1740_10.2.109.160_28 + + + r_network_dvportgroup-224 + dvPG_2457_10.2.10.8_29 + + + r_network_dvportgroup-478 + dvPG_4088_10.2.106.176_28 + + + r_network_dvportgroup-371 + dvPG_1831_10.2.114.32_28 + + + r_network_dvportgroup-514 + dvPG_3844_10.2.85.144_28 + + + r_network_dvportgroup-195 + dvPG_2408_10.2.134.192_26 + + + r_network_dvportgroup-242 + dvPG_4012_10.2.81.128_28 + + + r_network_dvportgroup-642 + dvPG_2351_10.8.34.208_28 + + + r_network_dvportgroup-26747 + dvPG_2279_165.234.164.32_27 + + + r_network_dvportgroup-367 + dvPG_1822_10.2.113.192_28 + + + r_network_dvportgroup-681 + dvPG_1761_10.2.110.176_28 + + + r_network_dvportgroup-521 + dvPG_1724_10.2.108.80_28 + + + r_network_dvportgroup-196 + dvPG_2407_10.2.134.128_26 + + + r_network_dvportgroup-520 + dvPG_3852_10.2.95.176_28 + + + r_network_dvportgroup-17307 + dvPG_0180_10.2.160.64_28 + + + r_network_dvportgroup-629 + dvPG_0116_10.221.3.0_24 + + + r_network_dvportgroup-13984 + dvPG_3440_10.2.122.176_28 + + + r_network_dvportgroup-17738 + dvPG_1909_10.221.10.144_28 + + + r_network_dvportgroup-26744 + dvPG_3951_165.234.37.0_28 + + + r_network_dvportgroup-7834 + dvPG_1969_10.2.119.160_28 + + + r_network_dvportgroup-3357 + dvPG_1931_10.2.115.128_28 + + + r_network_dvportgroup-393 + dvPG_3803_10.2.92.48_28 + + + r_network_dvportgroup-402 + dvPG_1790_10.2.111.224_28 + + + r_network_dvportgroup-610 + dvPG_2478_10.8.71.32_28 + + + r_network_dvportgroup-227 + dvPG_3700_10.2.13.32_28 + + + r_network_dvportgroup-215 + dvPG_3761_10.2.86.144_28 + + + r_network_dvportgroup-375 + dvPG_3940_10.2.97.240_28 + + + r_network_dvportgroup-19417 + dvPG_3323_10.2.151.224_28 + + + r_network_dvportgroup-26745 + dvPG_3950_165.234.142.0_24 + + + r_network_dvportgroup-19612 + dvPG_3513_10.2.161.64_28 + + + r_network_dvportgroup-185 + dvPG_4086_10.2.106.160_28 + + + r_network_dvportgroup-17749 + dvPG_1855_10.221.7.144_28 + + + r_network_dvportgroup-407 + dvPG_4064_10.2.101.160_28 + + + r_network_dvportgroup-427 + dvPG_3763_10.2.86.160_28 + + + r_network_dvportgroup-22061 + dvPG_3355_10.2.162.144_28 + + + r_network_dvportgroup-580 + dvPG_3545_10.30.0.0_20 + + + r_network_dvportgroup-632 + dvPG_4017_10.2.99.64_28 + + + r_network_dvportgroup-25456 + dvPG_3360_10.8.137.152_29 + + + r_network_dvportgroup-456 + dvPG_3858_10.2.97.32_28 + + + r_network_dvportgroup-437 + dvPG_1397_10.8.154.248_29 + + + r_network_dvportgroup-19477 + dvPG_3328_10.2.161.16_28 + + + r_network_dvportgroup-25242 + dvPG_3592_10.2.163.144_28 + + + r_network_dvportgroup-399 + dvPG_1752_10.2.110.32_28 + + + r_network_dvportgroup-637 + dvPG_3703_10.8.34.224_28 + + + r_network_dvportgroup-21822 + dvPG_3967_10.2.162.64_28 + + + r_network_dvportgroup-16289 + dvPG_3979_10.2.151.16_28 + + + r_network_dvportgroup-572 + dvPG_2401_10.2.133.0_26 + + + r_network_dvportgroup-317 + dvPG_1796_10.2.112.80_28 + + + r_network_dvportgroup-579 + dvPG_1711_10.2.107.128_28 + + + r_network_dvportgroup-8091 + dvPG_1989_10.2.119.224_28 + + + r_network_dvportgroup-489 + dvPG_1741_10.2.109.176_28 + + + r_network_dvportgroup-620 + dvPG_3663_10.2.12.208_28 + + + r_network_dvportgroup-198 + dvPG_3837_10.8.137.32_27 + + + r_network_dvportgroup-25811 + dvPG_3818_10.2.93.32_28 + + + r_network_dvportgroup-443 + dvPG_1781_10.2.111.160_28 + + + r_network_dvportgroup-535 + dvPG_0711_165.234.152.32_27 + + + r_network_dvportgroup-22032 + dvPG_3336_10.2.162.128_28 + + + r_network_dvportgroup-240 + dvPG_1798_10.2.112.112_28 + + + r_network_dvportgroup-1475 + dvPG_1849_10.2.115.16_28 + + + r_network_dvportgroup-25814 + dvPG_3821_10.2.93.80_28 + + + r_network_dvportgroup-238 + dvPG_1804_10.2.84.192_28 + + + r_network_dvportgroup-258 + dvPG_4042_10.2.100.144_28 + + + r_network_dvportgroup-1560 + dvPG_1927_10.2.115.48_28 + + + r_network_dvportgroup-216 + dvPG_3760_10.2.86.128_28 + + + r_network_dvportgroup-17731 + dvPG_1896_10.221.9.224_28 + + + r_network_dvportgroup-697 + dvPG_3667_165.234.44.64_28 + + + r_network_dvportgroup-3957 + dvPG_1942_10.2.118.0_28 + + + r_network_dvportgroup-738 + dvPG_SDC_TEL_MGMT + + + r_network_dvportgroup-220 + dvPG_2468_10.34.154.16_28 + + + r_network_dvportgroup-373 + dvPG_3828_10.2.95.64_28 + + + r_network_dvportgroup-190 + dvPG_3824_10.2.95.32_28 + + + r_network_dvportgroup-189 + dvPG_3554_165.234.121.0_25 + + + r_network_dvportgroup-414 + dvPG_0742_10.8.153.64_26 + + + r_network_dvportgroup-346 + dvPG_1718_10.2.107.240_28 + + + r_network_dvportgroup-205 + dvPG_1343_10.2.55.0_24 + + + r_network_dvportgroup-17732 + dvPG_1897_10.221.9.240_28 + + + r_network_dvportgroup-26895 + dvPG_3865_10.2.123.192_28 + + + r_network_dvportgroup-25243 + dvPG_3593_10.2.163.160_28 + + + r_network_dvportgroup-250 + dvPG_1772_10.2.111.80_28 + + + r_network_dvportgroup-336 + dvPG_4027_10.2.99.224_28 + + + r_network_dvportgroup-277 + dvPG_4028_10.2.99.240_28 + + + r_network_dvportgroup-26645 + dvPG_2003_10.2.166.48_28 + + + r_network_dvportgroup-17744 + dvPG_1850_10.221.7.64_28 + + + r_network_dvportgroup-611 + dvPG_3805_10.2.92.80_28 + + + r_network_dvportgroup-473 + dvPG_3690_10.2.80.80_28 + + + r_network_dvportgroup-282 + dvPG_1701_10.2.107.0_28 + + + r_network_dvportgroup-338 + dvPG_3862_10.2.97.112_28 + + + r_network_dvportgroup-698 + dvPG_1754_10.2.110.64_28 + + + r_network_dvportgroup-424 + dvPG_2451_165.234.44.16_28 + + + r_network_dvportgroup-3358 + dvPG_1932_10.2.115.144_28 + + + r_network_dvportgroup-6206 + dvPG_1959_10.2.118.128_28 + + + r_network_dvportgroup-31258 + dvPG_702_10.2.103.128_28 + + + r_network_dvportgroup-676 + dvPG_3674_10.8.154.224_28 + + + r_network_dvportgroup-260 + dvPG_4040_10.2.100.112_28 + + + r_network_dvportgroup-17740 + dvPG_1911_10.221.10.176_28 + + + r_network_dvportgroup-3961 + dvPG_1946_10.2.118.64_28 + + + r_network_dvportgroup-368 + dvPG_4090_10.8.137.64_28 + + + r_network_dvportgroup-547 + dvPG_0739_10.8.139.0_27 + + + r_network_dvportgroup-30147 + dvPG_3401_10.2.165.16_28 + + + r_network_dvportgroup-14518 + dvPG_3442_10.2.122.208_28 + + + r_network_dvportgroup-3579 + dvPG_1934_10.2.115.176_28 + + + r_network_dvportgroup-5450 + dvPG_0534_10.2.139.32_28 + + + r_network_dvportgroup-17335 + dvPG_0170_10.2.160.32_28 + + + r_network_dvportgroup-323 + dvPG_3931_10.2.97.96_28 + + + r_network_dvportgroup-377 + dvPG_3935_10.2.97.192_28 + + + r_network_dvportgroup-595 + dvPG_3814_10.2.92.224_28 + + + r_network_dvportgroup-326 + dvPG_1708_10.2.12.144_28 + + + r_network_dvportgroup-226 + dvPG_3739_10.2.84.16_28 + + + r_network_dvportgroup-7668 + dvPG_1949_10.2.119.112_28 + + + r_network_dvportgroup-18846 + dvPG_3320_10.2.151.176_28 + + + r_network_dvportgroup-705 + dvPG_4008_10.2.140.192_28 + + + r_network_dvportgroup-557 + dvPG_1763_10.2.110.208_28 + + + r_network_dvportgroup-519 + dvPG_3853_10.2.95.192_28 + + + r_network_dvportgroup-659 + dvPG_2396_165.234.44.8_29 + + + r_network_dvportgroup-4067 + dvPG_1951_10.2.118.160_28 + + + r_network_dvportgroup-540 + dvPG_3742_10.2.86.16_28 + + + r_network_dvportgroup-31429 + dvPG_3891_10.2.121.192_28 + + + r_network_dvportgroup-4569 + dvPG_1948_10.2.118.96_28 + + + r_network_dvportgroup-19995 + dvPG_3330_10.2.161.96_28 + + + r_network_dvportgroup-23969 + dvPG_1097_10.221.11.192_26 + + + r_network_dvportgroup-17719 + dvPG_1871_10.221.8.144_28 + + + r_network_dvportgroup-201 + dvPG_3836_10.8.137.0_27 + + + r_network_dvportgroup-4069 + dvPG_1953_10.2.118.192_28 + + + r_network_dvportgroup-26743 + dvPG_3834_10.2.95.96_28 + + + r_network_dvportgroup-7837 + dvPG_1988_10.2.119.208_28 + + + r_network_dvportgroup-584 + dvPG_4034_10.2.100.64_28 + + + r_network_dvportgroup-442 + dvPG_3650_10.2.12.0_28 + + + r_network_dvportgroup-349 + dvPG_1716_10.2.107.208_28 + + + r_network_dvportgroup-28936 + dvPG_202_10.2.0.0_28 + + + r_network_dvportgroup-6129 + dvPG_4076_10.2.101.224_28 + + + r_network_dvportgroup-191 + dvPG_1821_10.2.109.240_28 + + + r_network_dvportgroup-565 + dvPG_2403_10.2.133.128_26 + + + r_network_dvportgroup-623 + dvPG_3733_10.2.82.192_28 + + + r_network_dvportgroup-569 + dvPG_3701_10.2.87.0_24 + + + r_network_dvportgroup-8944 + dvPG_1842_10.2.114.144_28 + + + r_network_dvportgroup-17365 + dvPG_3422_10.2.121.128_28 + + + r_network_dvportgroup-25809 + dvPG_3816_10.2.93.0_28 + + + r_network_dvportgroup-312 + dvPG_1813_10.2.113.80_28 + + + r_network_dvportgroup-470 + dvPG_1394_10.2.60.0_23 + + + r_network_dvportgroup-19577 + dvPG_3512_10.2.161.48_28 + + + r_network_dvportgroup-3580 + dvPG_1935_10.2.115.192_28 + + + r_network_dvportgroup-449 + dvPG_3938_10.2.98.112_28 + + + r_network_dvportgroup-30481 + dvPG_1921_10.2.166.96_28 + + + r_network_dvportgroup-186 + dvPG_3766_10.2.86.176_28 + + + r_network_dvportgroup-180 + dvPG_1819_10.2.113.176_28 + + + r_network_dvportgroup-30656 + dvPG_1924_10.2.165.80_28 + + + r_network_dvportgroup-390 + dvPG_1712_10.2.107.144_28 + + + r_network_dvportgroup-17367 + dvPG_3424_10.2.121.160_28 + + + r_network_dvportgroup-379 + dvPG_4024_10.2.99.176_28 + + + r_network_dvportgroup-254 + dvPG_1734_10.2.108.240_28 + + + r_network_dvportgroup-26372 + dvPG_2000_10.2.166.0_28 + + + r_network_dvportgroup-26369 + dvPG_3684_10.2.93.128_28 + + + r_network_dvportgroup-17730 + dvPG_1895_10.221.9.208_28 + + + r_network_dvportgroup-11477 + dvPG_3419_10.2.121.80_28 + + + r_network_dvportgroup-17334 + dvPG_0169_10.2.160.16_28 + + + r_network_dvportgroup-6205 + dvPG_1960_10.2.118.144_28 + + + r_network_dvportgroup-23941 + dvPG_4006_10.2.140.160_28 + + + r_network_dvportgroup-730 + dvPG_0106_10.35.251.0_24 + + + r_network_dvportgroup-435 + dvPG_0045_10.2.8.0_24 + + + r_network_dvportgroup-498 + dvPG_1873_10.221.11.32_27 + + + r_network_dvportgroup-17336 + dvPG_0171_10.2.160.48_28 + + + r_network_dvportgroup-656 + dvPG_2398_10.2.132.64_26 + + + r_network_dvportgroup-354 + dvPG_4080_10.2.106.96_28 + + + r_network_dvportgroup-653 + dvPG_0163_10.2.34.0_24 + + + r_network_dvportgroup-17724 + dvPG_1886_10.221.9.64_28 + + + r_network_dvportgroup-270 + dvPG_1888_10.221.9.96_28 + + + r_network_dvportgroup-598 + dvPG_3779_10.2.84.128_28 + + + r_network_dvportgroup-448 + dvPG_4074_10.2.97.64_28 + + + r_network_dvportgroup-262 + dvPG_4041_10.2.100.128_28 + + + r_network_dvportgroup-3959 + dvPG_1944_10.2.118.32_28 + + + r_network_dvportgroup-19576 + dvPG_3511_10.2.161.32_28 + + + r_network_dvportgroup-25810 + dvPG_3817_10.2.93.16_28 + + + r_network_dvportgroup-230 + dvPG_3698_10.2.13.0_28 + + + r_network_dvportgroup-422 + dvPG_2344_10.8.34.0_27 + + + r_network_dvportgroup-337 + dvPG_3863_10.2.97.128_28 + + + r_network_dvportgroup-17338 + dvPG_0185_10.2.160.112_28 + + + r_network_dvportgroup-197 + dvPG_0086_10.8.38.0_24 + + + r_network_dvportgroup-628 + dvPG_2449_10.2.140.64_28 + + + r_network_dvportgroup-6207 + dvPG_1962_10.2.119.0_28 + + + r_network_dvportgroup-181 + dvPG_4013_10.2.81.160_28 + + + r_network_dvportgroup-8945 + dvPG_1843_10.2.114.160_28 + + + r_network_dvportgroup-735 + dvPG_0543_165.234.136.0_24_TEL + + + r_network_dvportgroup-474 + dvPG_3691_10.2.80.96_28 + + + r_network_dvportgroup-17714 + dvPG_3590_10.2.151.144_28 + + + r_network_dvportgroup-727 + dvPG_SDC_AVAYA_VMOTION + + + r_network_dvportgroup-619 + dvPG_3808_10.2.92.128_28 + + + r_network_dvportgroup-24536 + dvPG_3363_10.8.137.176_29 + + + r_network_dvportgroup-16288 + dvPG_3978_10.2.151.0_28 + + + r_network_dvportgroup-384 + dvPG_3851_10.2.95.160_28 + + + r_network_dvportgroup-6555 + dvPG_1964_10.2.119.32_28 + + + r_network_dvportgroup-501 + dvPG_1874_10.221.11.64_27 + + + r_network_dvportgroup-17722 + dvPG_1883_10.221.9.16_28 + + + r_network_dvportgroup-18845 + dvPG_3963_10.2.160.176_28 + + + r_network_dvportgroup-518 + dvPG_3854_10.2.95.208_28 + + + r_network_dvportgroup-218 + dvPG_3740_10.2.85.0_25 + + + r_network_dvportgroup-543 + dvPG_1722_10.2.108.48_28 + + + r_network_dvportgroup-24253 + dvPG_1063_10.2.160.208_28 + + + r_network_dvportgroup-7836 + dvPG_1987_10.2.119.192_28 + + + r_network_dvportgroup-586 + dvPG_1836_10.2.82.240_28 + + + r_network_dvportgroup-597 + dvPG_1399_165.234.125.0_24 + + + r_network_dvportgroup-169 + dvPG_SDC_MGMT_VM + + + r_network_dvportgroup-406 + dvPG_3829_10.2.95.80_28 + + + r_network_dvportgroup-17757 + dvPG_1863_10.221.8.16_28 + + + r_network_dvportgroup-243 + dvPG_1797_10.2.112.96_28 + + + r_network_dvportgroup-17729 + dvPG_1894_10.221.9.192_28 + + + r_network_dvportgroup-261 + dvPG_4056_10.2.101.128_28 + + + r_datastore_datastore-9690 + VMLINUX2_27_A9K_SYS + + + r_datastore_datastore-9695 + VMODM2_28_A9K_SYS + + + r_datastore_datastore-9696 + VMORACLE2_29_A9K_SYS + + + r_datastore_datastore-9697 + VMPS2_30_A9K_SYS + + + r_datastore_datastore-9698 + VMSQL2_31_A9K_SYS + + + r_datastore_datastore-9720 + VMTEL2_32_A9K_SYS + + + r_datastore_datastore-9725 + VMWAS2_33_A9K_SYS + + + r_datastore_datastore-9731 + VMWINDOWS2_34_A9K_SYS + + + r_datastore_datastore-9746 + VMAVAYA2_26_A9K_SYS + + + r_datastore_datastore-31548 + VMWINDOWS2_091_FS92_VR_MOVEIT + + + r_datastore_datastore-31549 + VMTEMPL2_009_FS92_MISC + + + r_datastore_datastore-31550 + VMWINDOWS2_092_FS92_VR + + + r_datastore_datastore-31551 + VMWINDOWS2_093_FS92_VR + + + r_datastore_datastore-31552 + VMWINDOWS2_094_FS92_VR + + + r_datastore_datastore-31553 + VMWINDOWS2_128_FS92_Gen + + + r_datastore_datastore-31554 + VMWINDOWS2_129_FS92_Gen + + + r_datastore_datastore-31555 + VMWINDOWS2_130_FS92_Gen + + + r_datastore_datastore-31556 + VMWINDOWS2_131_FS92_Gen + + + r_datastore_datastore-31557 + VMWINDOWS2_163_FS92_SQL + + + r_datastore_datastore-31558 + VMWINDOWS2_164_FS92_SQL + + + r_datastore_datastore-31562 + VMSQL2_016_FS92_TAX + + + r_datastore_datastore-31563 + VMSQL2_017_FS92_TAX + + + r_datastore_datastore-31564 + VMSQL2_034_FS92_VR + + + r_datastore_datastore-31565 + VMSQL2_112_FS92 + + + r_datastore_datastore-31566 + VMSQL2_113_FS92 + + + r_datastore_datastore-31567 + VMSQL2_114_FS92 + + + r_datastore_datastore-31568 + VMSQL2_115_FS92 + + + r_datastore_datastore-31569 + VMSQL2_116_FS92 + + + r_datastore_datastore-31570 + VMSQL2_117_FS92 + + + r_datastore_datastore-31571 + VMSQL2_118_FS92 + + + r_datastore_datastore-31572 + VMSQL2_119_FS92 + + + r_datastore_datastore-31573 + VMSQL2_120_FS92 + + + r_datastore_datastore-31574 + VMSQL2_133_FS92_CNDHFT + + + r_datastore_datastore-31575 + VMSQL2_134_FS92_CNDHFT + + + r_datastore_datastore-31576 + VMSQL2_135_FS92_CNDHFT + + + r_datastore_datastore-31634 + VMAVAYA2_107_FS92_VR + + + r_datastore_datastore-31635 + VMAVAYA2_108_FS92 + + + r_datastore_datastore-31636 + VMAVAYA2_109_FS92 + + + r_datastore_datastore-31637 + VMLINUX2_083_FS92_VR + + + r_datastore_datastore-31638 + VMLINUX2_084_FS92_VR + + + r_datastore_datastore-31639 + VMLINUX2_085_FS92 + + + r_datastore_datastore-31640 + VMLINUX2_086_FS92 + + + r_datastore_datastore-31641 + VMTEL2_029_FS92_VR + + + r_datastore_datastore-31642 + VMTEL2_030_FS92 + + + r_datastore_datastore-31643 + VMTEL2_031_FS92 + + + r_datastore_datastore-31644 + VMWAS2_069_FS92 + + + r_datastore_datastore-31645 + VMWAS2_070_FS92 + + + r_datastore_datastore-31646 + VMWAS2_097_FS92_VR + + + r_datastore_datastore-31647 + VMWAS2_098_FS92_VR + + + r_datastore_datastore-31872 + VMSCRATCH2_007_FS92 + + + + + + true + + l_folder_group-d1 + + l_dc_datacenter-141 + Minot Datacenter + + l_folder_group-v142 + vm + + l_folder_group-v21934 + Shared + + l_folder_group-v149 + Shared-Voice-Avaya + + l_vm_vm-28962 + itdmincmess8.nd.gov + + + + + l_folder_group-v29525 + _Delete Request + + + + l_folder_group-h143 + host + + l_computeResource_domain-s3819 + itdminvm-av01.nd.gov + + l_host_host-3821 + itdminvm-av01.nd.gov + + + l_resource_resgroup-3820 + Resources + + + + + l_network_network-3823 + VM Network + + + l_datastore_datastore-3822 + ITDMINVM-AV01_000_Local + + + + l_dc_datacenter-136 + GrandForks Datacenter + + l_folder_group-v137 + vm + + l_folder_group-v21933 + Shared + + l_folder_group-v148 + Shared-Voice-Avaya + + l_vm_vm-28963 + itdgfkcmess8.nd.gov + + + l_vm_vm-28223 + itdgfksm3mgt8.nd.gov + + + + + l_folder_group-v29524 + _Delete Request + + + + l_folder_group-h138 + host + + l_computeResource_domain-s3825 + itdgfvm-av01.nd.gov + + l_host_host-3827 + itdgfvm-av01.nd.gov + + + l_resource_resgroup-3826 + Resources + + + + + l_network_network-3829 + VM Network + + + l_datastore_datastore-3828 + ITDGFVM-AV01_000_Local + + + + l_dc_datacenter-131 + Fargo Datacenter + + l_folder_group-v132 + vm + + l_folder_group-v21932 + Shared + + l_folder_group-v147 + Shared-Voice-Avaya + + l_vm_vm-28964 + itdfgocmess8.nd.gov + + + l_vm_vm-28222 + itdfgosm2mgt8.nd.gov + + + + + l_folder_group-v29523 + _Delete Request + + + + l_folder_group-h133 + host + + l_computeResource_domain-s3877 + itdfarvm-av01.nd.gov + + l_host_host-3879 + itdfarvm-av01.nd.gov + + + l_resource_resgroup-3878 + Resources + + + + + l_network_network-3881 + VM Network + + + l_datastore_datastore-3880 + ITDFARVM-AV01_000_Local + + + + l_dc_datacenter-124 + DES Datacenter + + l_folder_group-v125 + vm + + l_folder_group-v21877 + DES + + l_folder_group-v21879 + DES-AntiVirus + + l_vm_vm-1774 + desnixav.nd.gov + + + + l_folder_group-v21878 + DES-CAD + + l_vm_vm-1771 + descadlive.nd.gov + + + l_vm_vm-1773 + descadtrain.nd.gov + + + l_vm_vm-1772 + descadcomt.nd.gov + + + l_vm_vm-1768 + descadcom.nd.gov + + + l_vm_vm-1766 + descaddbt.nd.gov + + + l_vm_vm-1770 + descaddb1.nd.gov + + + l_vm_vm-1767 + descaddb2.nd.gov + + + + + l_folder_group-v1760 + Discovered virtual machine + + + + l_folder_group-h126 + host + + l_computeResource_domain-c129 + DES1 + + l_host_host-1769 + itdappvmdes1.nd.gov + + + l_host_host-1761 + itdappvmdes2.nd.gov + + + l_resource_resgroup-130 + Resources + + + + + l_network_network-1765 + PG-10.166.64.0/23 + + + l_datastore_datastore-1762 + VMDES1_10_V3700 + + + l_datastore_datastore-1763 + VMDES1_11_V3700 + + + l_datastore_datastore-1764 + VMDES1_000_V3700_SYS + + + + l_dc_datacenter-117 + DCN Datacenter + + l_folder_group-v118 + vm + + l_folder_group-v22110 + Shared + + l_folder_group-v22111 + Shared-Video-Polycomm + + l_vm_vm-3917 + itdrpms.nd.gov + + + + + l_folder_group-v21876 + ITD + + l_folder_group-v22109 + ITD-POC-Networking + + l_vm_vm-3904 + itdjuniperspace.nd.gov + + + l_vm_vm-28332 + panoramalab.nd.gov + + + + l_folder_group-v21880 + ITD-EDUTech-K12FIM + + l_vm_vm-3897 + itdk12adfs1.k12.nd.us + + + + + l_folder_group-v21875 + Infra + + l_folder_group-v22108 + Infra-Networking-MGT + + l_vm_vm-3906 + info.state.nd.us + + + l_vm_vm-3902 + k12radius.state.nd.us + + + l_vm_vm-3900 + itdradius4.nd.gov + + + l_vm_vm-3899 + itdnwstorage.nd.gov + + + l_vm_vm-3903 + itdradius3.nd.gov + + + l_vm_vm-3914 + itdnettools.nd.gov + + + l_vm_vm-3907 + itdtftp.nd.gov + + + + l_folder_group-v28275 + Infra-ActiveDirectory + + l_vm_vm-28216 + itddc22.nd.gov + + + + l_folder_group-v21938 + Infra-Networking-Filtering + + + l_folder_group-v21937 + Infra-Networking-NetBrain + + l_vm_vm-23203 + itdnbfront1.nd.gov + + + + l_folder_group-v21936 + Infra-Networking-Cacti + + l_vm_vm-3918 + cacti2.state.nd.us + + + l_vm_vm-3919 + itdcacti.nd.gov + + + + l_folder_group-v28276 + Infra-PTA + + l_vm_vm-28215 + itdpta2.nd.gov + + + + l_folder_group-v21935 + Infra-WINS + + l_vm_vm-3909 + ns9.nd.gov + + + + l_folder_group-v35901 + Infra-Monitoring-Solarwinds + + l_vm_vm-35631 + itdslrwndspoll3.nd.gov + + + + + l_folder_group-v150 + _Delete Request + + + l_folder_group-v152 + Telecomm Servers + + + l_folder_group-v153 + _Templates + + + + l_folder_group-h119 + host + + l_computeResource_domain-c122 + DCN1 + + l_host_host-3915 + itdbisvm-dcn02.nd.gov + + + l_host_host-3887 + itdbisvm-dcn01.nd.gov + + + l_resource_resgroup-123 + Resources + + + + + l_network_dvportgroup-35444 + dvPG_0023_165.234.65.208_28 + + + l_network_dvportgroup-784 + dvPG_PDC_DCN_MGMT + + + l_network_dvportgroup-28220 + dvPG_1983_10.2.160.144_28 + + + l_network_dvportgroup-28219 + dvPG_1806_10.2.113.16_28 + + + l_network_dvportgroup-790 + dvPG_0015_165.234.65.224_27 + + + l_network_dvportgroup-788 + dvPG_0524_10.0.7.0_27 + + + l_network_dvportgroup-791 + dvPG_0543_165.234.136.0_24_DCN + + + l_network_dvportgroup-789 + dvPG_PDC_DCN_VMOTION + + + l_network_dvportgroup-787 + dvPG_3519_10.50.2.0_24 + + + l_datastore_datastore-5794 + VMDCN1_20_V5K + + + l_datastore_datastore-5795 + VMDCN1_21_V5K + + + + l_dc_datacenter-2 + Primary Datacenter + + l_folder_group-v3 + vm + + l_vm_vm-51768 + Red Hat Enterprise Linux 7 - Master Template + + + l_folder_group-v9878 + _Migrated to Azure + + + l_folder_group-v34208 + DEQ + + l_folder_group-v34725 + DEQ-Web-Portal-Data + + l_vm_vm-34672 + itddeqnetp1.nd.gov + + + + l_folder_group-v34209 + DEQ-Waste-Transporter + + l_vm_vm-33309 + itddeqappp1.nd.gov + + + + l_folder_group-v50902 + DEQ-nVIRO + + l_vm_vm-50778 + itddeqnvsqlp1.nd.gov + + + l_vm_vm-50776 + itddeqnvp1.nd.gov + + + + + l_folder_group-v21659 + HED + + + l_folder_group-v21669 + NDUS + + l_folder_group-v21999 + NDUS-Cognos + + l_vm_vm-3297 + itdcogndus.ndcloud.gov + + + + l_folder_group-v22032 + NDUS-TimeLabor + + l_vm_vm-2595 + itdhekabatest.nd.gov + + + l_vm_vm-2774 + itdhekabaprod.nd.gov + + + + + l_folder_group-v21656 + DOH + + l_folder_group-v22015 + DOH-Video + + l_vm_vm-3160 + itddohvid.itd.nd.gov + + + + l_folder_group-v21394 + DOH-USAFoodSafety + + l_vm_vm-3551 + itddohimsp1.nd.gov + + + + l_folder_group-v22014 + DOH-WIC + + l_vm_vm-42534 + itddohlegendp3.nd.gov + + + l_vm_vm-41619 + itddohewicsqlp1.nd.gov + + + l_vm_vm-33989 + itddohewicsqlt1.nd.gov + + + l_vm_vm-2833 + itddohlegendp2.nd.gov + + + + l_folder_group-v21985 + DOH-Maven + + l_vm_vm-2244 + itdcatp109-146.nd.gov + + + + l_folder_group-v21968 + DOH-STEVE + + l_vm_vm-3512 + itdapp10.nd.gov + + + + l_folder_group-v21951 + DOH-SAS + + l_vm_vm-3290 + itddohsasp1.nd.gov + + + + l_folder_group-v21393 + DOH-Shared-App + + l_vm_vm-3223 + itddohnetp3.nd.gov + + + + l_folder_group-v22026 + DOH-EVVE + + l_vm_vm-2132 + itdevve1.nd.gov + + + + l_folder_group-v805 + DOH-PRS + + l_vm_vm-3143 + itddohprsp1.nd.gov + + + + l_folder_group-v46616 + DOH-RedCap + + + + l_folder_group-v21671 + DES + + l_folder_group-v21961 + DES-CAD + + l_vm_vm-1557 + descadarchive.nd.gov + + + + l_folder_group-v21946 + DES-EMGrantsPro + + + l_folder_group-v21136 + DES-WebEOC + + l_vm_vm-3150 + itddesnetp1.nd.gov + + + + l_folder_group-v22028 + DES-GeoComm + + l_vm_vm-3010 + itdgeolynx2.itd.nd.gov + + + l_vm_vm-28384 + itdgeolynx1.nd.gov + + + + + l_folder_group-v21653 + BND + + l_folder_group-v29689 + BND-Reporting + + l_vm_vm-29688 + bnd1177.nd.gov + + + + l_folder_group-v21133 + BND-Calyx + + l_vm_vm-3155 + bndapp12.bnd.nd.gov + + + + l_folder_group-v21232 + BND-Shared-App + + l_vm_vm-3026 + bnd0704.nd.gov + + + l_vm_vm-36796 + bnd1206.nd.gov + + + l_vm_vm-3064 + bnd0225.bnd.nd.gov + + + l_vm_vm-2773 + bnd0703.nd.gov + + + l_vm_vm-3074 + bnd0224.bnd.nd.gov + + + + l_folder_group-v793 + BND-Fiserv + + l_vm_vm-39095 + bnd1216.nd.gov + + + l_vm_vm-3011 + bnd0476.nd.gov + + + l_vm_vm-3215 + bnd0490.nd.gov + + + l_vm_vm-39097 + bnd1220.nd.gov + + + l_vm_vm-3553 + bnd0486.nd.gov + + + + l_folder_group-v21134 + BND-BondBanking + + l_vm_vm-3558 + bnd0556.nd.gov + + + l_vm_vm-2917 + bnd0557.nd.gov + + + + l_folder_group-v21233 + BND-SQL + + l_vm_vm-2958 + bnd0297.nd.gov + + + l_vm_vm-3067 + bnd0298.nd.gov + + + + l_folder_group-v21230 + BND-MFA + + l_vm_vm-2448 + bnd0887.nd.gov + + + + l_folder_group-v37264 + BND-APCheck + + l_vm_vm-37261 + bnd1207.nd.gov + + + + l_folder_group-v20471 + BND-WebSphere + + l_vm_vm-1428 + bnd0328.bnd.nd.gov + + + l_vm_vm-1430 + bnd0326.bnd.nd.gov + + + l_vm_vm-1429 + bnd0327.bnd.nd.gov + + + + l_folder_group-v21135 + BND-HELMS + + l_vm_vm-2771 + bnd0437.bnd.nd.gov + + + l_vm_vm-2962 + bnd0434.bnd.nd.gov + + + l_vm_vm-3502 + bnd0555.nd.gov + + + l_vm_vm-3499 + bnd0433.bnd.nd.gov + + + l_vm_vm-3548 + bnd0430.bnd.nd.gov + + + l_vm_vm-3025 + bnd0432.bnd.nd.gov + + + l_vm_vm-3285 + bnd0431.bnd.nd.gov + + + l_vm_vm-2973 + bnd0436.bnd.nd.gov + + + + l_folder_group-v796 + BND-MFT + + l_vm_vm-2760 + bnd0603.nd.gov + + + l_vm_vm-3549 + bnd0602.nd.gov + + + l_vm_vm-3483 + bnd0601.nd.gov + + + l_vm_vm-2722 + bnd0600.nd.gov + + + + l_folder_group-v797 + BND-FUNDTECH + + l_vm_vm-3089 + bnd0425.bnd.nd.gov + + + l_vm_vm-2926 + bnd0656.nd.gov + + + l_vm_vm-3542 + bnd0824.nd.gov + + + l_vm_vm-3283 + bnd0427.bnd.nd.gov + + + l_vm_vm-3216 + bnd0426.bnd.nd.gov + + + l_vm_vm-2835 + bnd0424.bnd.nd.gov + + + l_vm_vm-3282 + bnd0655.nd.gov + + + l_vm_vm-3507 + bnd0825.nd.gov + + + + l_folder_group-v27600 + BND-Desktop-PatchMGT + + l_vm_vm-27552 + bnd1154.nd.gov + + + + l_folder_group-v21959 + BND-Whitelisting-Linux + + l_vm_vm-2250 + bnd0658.nd.gov + + + + l_folder_group-v23823 + BND-PortNox + + + l_folder_group-v21948 + BND-DLP-Windows + + l_vm_vm-3470 + bnd0553.nd.gov + + + l_vm_vm-3293 + bnd0889.nd.gov + + + l_vm_vm-3301 + bnd0554.nd.gov + + + l_vm_vm-2822 + bnd0552.nd.gov + + + l_vm_vm-3061 + bnd0558.nd.gov + + + + l_folder_group-v21960 + BND-Sendero + + l_vm_vm-15050 + bnd1031.nd.gov + + + + l_folder_group-v21379 + BND-PitneyBowes + + l_vm_vm-2462 + itdbndpbprod.bnd.nd.gov + + + l_vm_vm-37262 + bnd1218.nd.gov + + + + l_folder_group-v21956 + BND-Nessus + + + l_folder_group-v21958 + BND-Whitelisting-Windows + + l_vm_vm-2545 + bnd0657.nd.gov + + + + l_folder_group-v21231 + BND-Jreport + + l_vm_vm-9428 + bnd0969.nd.gov + + + l_vm_vm-9429 + bnd0970.nd.gov + + + + l_folder_group-v792 + BND-FIS + + l_vm_vm-3076 + bnd0856.nd.gov + + + l_vm_vm-3544 + bnd0527.nd.gov + + + l_vm_vm-2880 + bnd0532.nd.gov + + + l_vm_vm-3154 + bnd0528.nd.gov + + + l_vm_vm-3375 + bnd0536.nd.gov + + + l_vm_vm-2825 + bnd0526.nd.gov + + + l_vm_vm-3084 + bnd0857.nd.gov + + + l_vm_vm-2836 + bnd0530.nd.gov + + + l_vm_vm-3557 + bnd0531.nd.gov + + + l_vm_vm-3280 + bnd0873.nd.gov + + + l_vm_vm-2445 + bnd0535.nd.gov + + + l_vm_vm-3295 + bnd0533.nd.gov + + + l_vm_vm-3387 + bnd0529.nd.gov + + + + l_folder_group-v21957 + BND-DLP-Linux + + l_vm_vm-1308 + bnd0550.nd.gov + + + + + l_folder_group-v41323 + Discovered virtual machine + + + l_folder_group-v21665 + SOS + + l_folder_group-v21944 + SOS-BPRO + + l_vm_vm-38690 + itdsosvipp1.nd.gov + + + l_vm_vm-38694 + itdsosvoicest1.nd.gov + + + l_vm_vm-3310 + itdsosbpiwp2.itd.nd.gov + + + l_vm_vm-2914 + itdsosbpwt1.itd.nd.gov + + + l_vm_vm-38688 + itdsosvoicesp1.nd.gov + + + l_vm_vm-3317 + itdsosbpwt2.itd.nd.gov + + + l_vm_vm-38693 + itdsosvipp2.nd.gov + + + l_vm_vm-38689 + itdsosvoicesp2.nd.gov + + + l_vm_vm-3407 + itdsosbpiwp1.itd.nd.gov + + + l_vm_vm-38695 + itdsosvipt1.nd.gov + + + + l_folder_group-v8303 + SOS-BLS + + l_vm_vm-3016 + itdsosblswebt1.nd.gov + + + l_vm_vm-3151 + itdsosblswks1.nd.gov + + + l_vm_vm-8177 + itdsosblswebp1.nd.gov + + + l_vm_vm-8178 + itdsosblsappp1.nd.gov + + + l_vm_vm-2535 + itdsosblsappt1.nd.gov + + + + l_folder_group-v817 + SOS-CentralIndexing + + l_vm_vm-2431 + itdsosindexp2.nd.gov + + + l_vm_vm-2355 + itdsosindexp1.nd.gov + + + l_vm_vm-2590 + itdsoscisqlp1.nd.gov + + + + + l_folder_group-v154 + _Clone Request + + l_vm_vm-43350 + itdbcompare1.nd.gov_AutoClone_165 + + + l_vm_vm-46362 + itdjsnuip1.nd.gov-covid_clone + + + l_vm_vm-39717 + itdvpdevivr.nd.gov-longtermclone20191211 + + + l_vm_vm-44501 + itdvbrickdb1.video.nd.gov_AutoClone_2176 + + + l_vm_vm-39715 + itdvpepmbis.nd.gov-longtermclone20191211 + + + + l_folder_group-v21667 + Shared + + l_folder_group-v51786 + Shared-MariaDB + + l_vm_vm-48862 + itdmariadbp1.nd.gov + + + + l_folder_group-v21529 + Shared-IIS + + l_vm_vm-3166 + itdwww9.nd.gov + + + l_vm_vm-3473 + itdwwwdev7.nd.gov + + + l_vm_vm-2461 + itdwww3.nd.gov + + + l_vm_vm-2533 + itdwww11.nd.gov + + + l_vm_vm-2444 + itdwwwdev3.nd.gov + + + l_vm_vm-3396 + itdwwwdev9.nd.gov + + + l_vm_vm-2874 + itdwwwdev8.nd.gov + + + l_vm_vm-2769 + itdwww10.nd.gov + + + l_vm_vm-2869 + itdwww7.nd.gov + + + l_vm_vm-3316 + itdwww8.nd.gov + + + + l_folder_group-v21531 + Shared-Video-Renovo + + l_vm_vm-30640 + itdk12vidwebp1.nd.gov + + + l_vm_vm-30639 + itdk12vidappp1.nd.gov + + + + l_folder_group-v21527 + Shared-Email-Lync + + l_vm_vm-25222 + itdskypefet1.testnd.gov + + + l_vm_vm-2823 + itdskypebis2.nd.gov + + + l_vm_vm-2426 + itdskypedir1.nd.gov + + + l_vm_vm-2588 + itdskypeedge1.nd.gov + + + l_vm_vm-3131 + itdskypebis1.nd.gov + + + l_vm_vm-25223 + itdskypeedget1.testnd.gov + + + + l_folder_group-v21530 + Shared-SCCM + + l_vm_vm-2450 + itdsccm1.nd.gov + + + l_vm_vm-33658 + itdsccmup1.nd.gov + + + l_vm_vm-35161 + itdsccmwsusup1.nd.gov + + + l_vm_vm-2539 + itdsccmwsus1.nd.gov + + + + l_folder_group-v21524 + Shared-AddressPro + + l_vm_vm-2568 + itdaddressprop1.nd.gov + + + l_vm_vm-2441 + itdaddressprot1.nd.gov + + + + l_folder_group-v22094 + Shared-HEAT-SQL + + l_vm_vm-1545 + itdsqlheatrasp1.nd.gov + + + + l_folder_group-v22005 + Shared-Video-Devos + + l_vm_vm-3400 + itddevos.nd.gov + + + + l_folder_group-v22000 + Shared-ComplianceSheriff + + l_vm_vm-3218 + itdcompliance1.nd.gov + + + l_vm_vm-44843 + itdcompliance2.nd.gov + + + + l_folder_group-v21382 + Shared-dotNet + + l_vm_vm-2890 + itdnet35t2.itd.nd.gov + + + l_vm_vm-9066 + itdnett2.nd.gov + + + l_vm_vm-9640 + itdnetu2.nd.gov + + + l_vm_vm-3203 + itdnet35p2.itd.nd.gov + + + l_vm_vm-3405 + itdnet35t1.itd.nd.gov + + + l_vm_vm-25505 + itdnetp4.nd.gov + + + l_vm_vm-3140 + itdnett1.itd.nd.gov + + + l_vm_vm-9642 + itdnetp2.nd.gov + + + l_vm_vm-2377 + itdnet35p1.itd.nd.gov + + + l_vm_vm-2938 + itdnetp1.itd.nd.gov + + + + l_folder_group-v21992 + Shared-Citrix + + l_vm_vm-3363 + itdcitrixlic.nd.gov + + + + l_folder_group-v21451 + Shared-SystemZ + + l_vm_vm-3224 + itdrpm1.nd.gov + + + + l_folder_group-v22067 + Shared-SharePoint + + l_vm_vm-2808 + itdowapptest.nd.gov + + + l_vm_vm-2768 + itdspsprod.nd.gov + + + l_vm_vm-3214 + itdspstest.nd.gov + + + l_vm_vm-3141 + itdowaprod.nd.gov + + + l_vm_vm-2550 + itdwssprod.nd.gov + + + l_vm_vm-3284 + itdspsprodserv.nd.gov + + + l_vm_vm-2921 + itdwsstest.nd.gov + + + + l_folder_group-v20495 + Shared-Drupal + + + l_folder_group-v22078 + Shared-Voice-Redsky + + l_vm_vm-29909 + itdredskyaes1.nd.gov + + + + l_folder_group-v21969 + Shared-App + + l_vm_vm-3380 + itdapp8.nd.gov + + + l_vm_vm-3309 + itdapp7.itd.nd.gov + + + l_vm_vm-3005 + itdapp11.nd.gov + + + + l_folder_group-v20475 + Shared-EDMS-Adobe + + l_vm_vm-10173 + itdaem1prd.nd.gov + + + + l_folder_group-v22077 + Shared-RemoteDesktopServices + + + l_folder_group-v22047 + Shared-MasterDataMGT-MC + + + l_folder_group-v21989 + Shared-Tomcat + + l_vm_vm-2288 + itdcatt2.nd.gov + + + l_vm_vm-2263 + itdcatp2.nd.gov + + + l_vm_vm-2261 + itdcatp3.nd.gov + + + + l_folder_group-v811 + Shared-Email-Exchange + + l_vm_vm-25220 + itdexcht1.testnd.gov + + + l_vm_vm-27928 + itdfsw.nd.gov + + + l_vm_vm-2475 + itdtexcas1.ndtestdev.nd.dev + + + l_vm_vm-2474 + itdtexmbx1.ndtestdev.nd.dev + + + l_vm_vm-2600 + itdexchmbxbis1.nd.gov + + + l_vm_vm-2603 + itdexchmbxbis2.nd.gov + + + l_vm_vm-25221 + itdexcht2.testnd.gov + + + l_vm_vm-25739 + itdfsw1.testnd.gov + + + l_vm_vm-2601 + itdexchcasbis1.nd.gov + + + l_vm_vm-31612 + itdexchassess1.nd.gov + + + + l_folder_group-v22041 + Shared-K12-ActiveDirectory + + l_vm_vm-3086 + itdk12testdc4.k12tst.nd.us + + + l_vm_vm-2832 + itdk12stgdc4.stg.k12.nd.us + + + l_vm_vm-2826 + itdk12dc10.k12.nd.us + + + l_vm_vm-2966 + itdk12dc7.k12.nd.us + + + l_vm_vm-3007 + itdk12dc9.k12.nd.us + + + l_vm_vm-2598 + itdk12stgdc3.stg.k12.nd.us + + + l_vm_vm-3233 + itdk12dc8.k12.nd.us + + + + l_folder_group-v20466 + Shared-SQL + + l_vm_vm-3088 + itddpa1.nd.gov + + + l_vm_vm-1362 + itdsql16rasp1.nd.gov + + + l_vm_vm-1556 + itdsql16p1.nd.gov + + + l_vm_vm-1579 + itdsql14p2.nd.gov + + + l_vm_vm-28909 + itdsql16rasq1.nd.gov + + + l_vm_vm-43967 + itdsql19rasp1.nd.gov + + + l_vm_vm-1748 + itdsqldba2.nd.gov + + + l_vm_vm-1351 + itdsql12rasp1.nd.gov + + + l_vm_vm-1550 + itdsql14p1.nd.gov + + + l_vm_vm-1572 + itdsql12p3.nd.gov + + + l_vm_vm-2542 + itdsqlrdp2.nd.gov + + + l_vm_vm-1352 + itdsql14rasp1.nd.gov + + + l_vm_vm-1749 + itdintsql12p1.nd.gov + + + l_vm_vm-1581 + itdsql12p1.nd.gov + + + l_vm_vm-39292 + itdsql19p1.nd.gov + + + l_vm_vm-27226 + itdsql16p3.nd.gov + + + l_vm_vm-15051 + itdintsql16p1.nd.gov + + + + l_folder_group-v22059 + Shared-NetMotion + + l_vm_vm-2877 + itdnetmotionp8.nd.gov + + + l_vm_vm-3208 + itdnetmotionp9.nd.gov + + + + l_folder_group-v809 + Shared-PeopleSoft-State + + l_vm_vm-2472 + itdcndstlwp.nd.gov + + + l_vm_vm-2361 + itdcndstbooks1.nd.gov + + + l_vm_vm-48797 + itdcndsh16app1.nd.gov + + + l_vm_vm-51789 + itdcndslscorm16.nd.gov + + + l_vm_vm-2586 + itdcndsthrdp6.nd.gov + + + l_vm_vm-44700 + itdcndsf16app2.nd.gov + + + l_vm_vm-22730 + itdcndstrwp2.nd.gov + + + l_vm_vm-45725 + itdcndstfrdp8.nd.gov + + + l_vm_vm-2562 + itdcndstrwp.nd.gov + + + l_vm_vm-22729 + itdcndstrwp1.nd.gov + + + l_vm_vm-45724 + itdcndstlrdp8.nd.gov + + + l_vm_vm-22731 + itdcndstlwp1.nd.gov + + + l_vm_vm-22734 + itdcndsthwp2.nd.gov + + + l_vm_vm-45723 + itdcndsthrdp8.nd.gov + + + l_vm_vm-2384 + itdcndsthwp.nd.gov + + + l_vm_vm-44702 + itdcndsf16wp.nd.gov + + + l_vm_vm-6087 + itdcndstfrdp6.nd.gov + + + l_vm_vm-2566 + itdcndstrapp1.nd.gov + + + l_vm_vm-38687 + itdcndstescore.nd.gov + + + l_vm_vm-2440 + itdcndstupk1.nd.gov + + + l_vm_vm-2383 + itdcndstes02.nd.gov + + + l_vm_vm-45722 + itdcndstrrdp8.nd.gov + + + l_vm_vm-2436 + itdcndstgateway.nd.gov + + + l_vm_vm-49803 + itdcnds16es01.nd.gov + + + l_vm_vm-49805 + itdcnds16es03.nd.gov + + + l_vm_vm-48381 + itdcndsh16ps.nd.gov + + + l_vm_vm-48798 + itdcndsh16app2.nd.gov + + + l_vm_vm-49804 + itdcnds16es02.nd.gov + + + l_vm_vm-44705 + itdcndsf16sowp.nd.gov + + + l_vm_vm-2366 + itdcndstlscorm1.nd.gov + + + l_vm_vm-2572 + itdcndstrps.nd.gov + + + l_vm_vm-27452 + itdcndstphire.nd.gov + + + l_vm_vm-2470 + itdcndstlapp1.nd.gov + + + l_vm_vm-2569 + itdcndstlapp2.nd.gov + + + l_vm_vm-44704 + itdcndsf16wp2.nd.gov + + + l_vm_vm-2367 + itdcndstrapp2.nd.gov + + + l_vm_vm-44701 + itdcndsf16ps.nd.gov + + + l_vm_vm-2350 + itdcndstlps.nd.gov + + + l_vm_vm-29529 + itdcndsfpdb16.nd.gov + + + l_vm_vm-2433 + itdcndstes03.nd.gov + + + l_vm_vm-2430 + itdcndsthcgwp.nd.gov + + + l_vm_vm-40142 + itdcndshpdb16.nd.gov + + + l_vm_vm-2575 + itdcndstlrdp6.nd.gov + + + l_vm_vm-2647 + itdcndsturdp1.nd.gov + + + l_vm_vm-22732 + itdcndstlwp2.nd.gov + + + l_vm_vm-22733 + itdcndsthwp1.nd.gov + + + l_vm_vm-44699 + itdcndsf16app1.nd.gov + + + l_vm_vm-37204 + itdcndsrpdb16.nd.gov + + + l_vm_vm-44703 + itdcndsf16wp1.nd.gov + + + l_vm_vm-2457 + itdcndstes01.nd.gov + + + l_vm_vm-33079 + itdcndstphirew.nd.gov + + + l_vm_vm-2428 + itdcndstrrdp6.nd.gov + + + l_vm_vm-40141 + itdcndslpdb16.nd.gov + + + + l_folder_group-v20455 + Shared-Video-Pexip + + l_vm_vm-16923 + itdpexipconfnd5.video.nd.gov + + + l_vm_vm-16922 + itdpexipconfnd4.video.nd.gov + + + l_vm_vm-8173 + itdpexiprp1.nd.gov + + + l_vm_vm-1281 + itdpexipmgmtnd.video.nd.gov + + + l_vm_vm-16924 + itdpexipconfnd6.video.nd.gov + + + l_vm_vm-16871 + itdpexipconfnd2.video.nd.gov + + + l_vm_vm-16870 + itdpexipconfnd1.video.nd.gov + + + l_vm_vm-16921 + itdpexipconfnd3.video.nd.gov + + + + l_folder_group-v21982 + Shared-Bomgar + + l_vm_vm-45383 + itdbomgar2.nd.gov + + + l_vm_vm-2162 + itdbomgar1.nd.gov + + + + l_folder_group-v44842 + Shared-ServiceNow + + l_vm_vm-44841 + itdesmmid1.nd.gov + + + + l_folder_group-v21539 + Shared-K12-ViewPoint + + + l_folder_group-v21526 + Shared-Email-ListServ + + l_vm_vm-41444 + itdlist.nd.gov + + + + l_folder_group-v22097 + Shared-Teammate + + l_vm_vm-9147 + itdteamp1.nd.gov + + + + l_folder_group-v20447 + Shared-Voice-Avaya + + l_vm_vm-29908 + itdwfoaes4.nd.gov + + + l_vm_vm-1487 + itdbisweblm.nd.gov + + + l_vm_vm-29905 + itd1xaes2.nd.gov + + + l_vm_vm-9106 + itdavayarec.nd.gov + + + l_vm_vm-29907 + itdbiscmsvrb.nd.gov + + + l_vm_vm-24198 + itdbiscms.nd.gov + + + l_vm_vm-28217 + itdbissm1mgt8.nd.gov + + + l_vm_vm-17508 + itdbissal.nd.gov + + + l_vm_vm-29906 + itdbiscmsvra.nd.gov + + + l_vm_vm-28218 + itdbissysmgr8.nd.gov + + + l_vm_vm-1503 + itdavayasbc.nd.gov + + + + l_folder_group-v20449 + Shared-Voice-Avaya-IVR + + l_vm_vm-36910 + itdvpas2bis.nd.gov + + + l_vm_vm-37502 + itdvpdevas4.nd.gov-rebuilt + + + l_vm_vm-1494 + itdvpdevspeech.nd.gov + + + l_vm_vm-1489 + itdvpspeech1bis.nd.gov + + + l_vm_vm-37500 + itdvpdevas2.nd.gov-rebuilt + + + l_vm_vm-36912 + itdvpas3bis.nd.gov + + + l_vm_vm-37501 + itdvpdevas3.nd.gov-rebuilt + + + l_vm_vm-1532 + itdvpmpp1bis.nd.gov + + + l_vm_vm-33872 + itdvpdevivr.nd.gov + + + l_vm_vm-36911 + itdvpas1bis.nd.gov + + + l_vm_vm-1500 + itdvpepmbis.nd.gov + + + l_vm_vm-37499 + itdvpdevas1.nd.gov-rebuilt + + + l_vm_vm-36965 + itdvpas4bis.nd.gov + + + + l_folder_group-v21596 + Shared-WebSphere + + l_vm_vm-1388 + itdintws8p2a.nd.gov + + + l_vm_vm-1381 + itdintws8p3a.nd.gov + + + l_vm_vm-1379 + itdintws8dmgrp1.nd.gov + + + l_vm_vm-1415 + itdws9p1.nd.gov + + + l_vm_vm-1382 + itdintws8p1a.nd.gov + + + l_vm_vm-1928 + itdintws8f1.itd.nd.gov + + + l_vm_vm-1935 + itdws8f1.itd.nd.gov + + + l_vm_vm-1411 + itdws9dmgrp1.nd.gov + + + l_vm_vm-1390 + itdintws9dmgrp1.nd.gov + + + l_vm_vm-1412 + itdws8p3a.nd.gov + + + l_vm_vm-1385 + itdintws9p3.nd.gov + + + l_vm_vm-1409 + itdws8p4a.nd.gov + + + l_vm_vm-1389 + itdintws8p4a.nd.gov + + + l_vm_vm-41345 + itdws9pf1.nd.gov + + + l_vm_vm-1384 + itdintws9p1.nd.gov + + + l_vm_vm-1395 + itdws8p1a.nd.gov + + + l_vm_vm-1383 + itdintws9pf1.nd.gov + + + l_vm_vm-1394 + itdws8p2a.nd.gov + + + l_vm_vm-1418 + itdws9p3.nd.gov + + + l_vm_vm-1391 + itdintws9p4.nd.gov + + + l_vm_vm-1417 + itdws9p2.nd.gov + + + l_vm_vm-1393 + itdintws9p2.nd.gov + + + l_vm_vm-1410 + itdws8dmgrp1.nd.gov + + + l_vm_vm-1416 + itdws9p4.nd.gov + + + + l_folder_group-v22089 + Shared-SharePoint-SQL + + l_vm_vm-1747 + itdsql12spp1.nd.gov + + + + l_folder_group-v21538 + Shared-PowerSchool + + l_vm_vm-1047 + itdps-strasburg.nd.gov + + + l_vm_vm-1124 + itdps-enderlin.nd.gov + + + l_vm_vm-29471 + itdps-testoem.nd.gov + + + l_vm_vm-1171 + itdps-newtown.nd.gov + + + l_vm_vm-1189 + itdps-fargo2.nd.gov + + + l_vm_vm-1151 + itdps-tgu.nd.gov + + + l_vm_vm-1161 + itdps-newrockfo.nd.gov + + + l_vm_vm-1120 + itdps-mandandb.nd.gov + + + l_vm_vm-1186 + itdps-griggscou.nd.gov + + + l_vm_vm-1011 + itdps-rugby.nd.gov + + + l_vm_vm-1127 + itdps-bismardb.nd.gov + + + l_vm_vm-1045 + itdps-hfsm.nd.gov + + + l_vm_vm-1029 + itdps-beach.nd.gov + + + l_vm_vm-1159 + itdps-wilton.nd.gov + + + l_vm_vm-1123 + itdps-bismarrpt.nd.gov + + + l_vm_vm-1026 + itdps-wyndmere.nd.gov + + + l_vm_vm-1116 + itdps-warwick.nd.gov + + + l_vm_vm-1052 + itdps-washburn.nd.gov + + + l_vm_vm-1199 + itdps-lamoure.nd.gov + + + l_vm_vm-1208 + itdps-newenglan.nd.gov + + + l_vm_vm-14920 + itdps-fargodb.nd.gov + + + l_vm_vm-902 + itdps-westfatst.nd.gov + + + l_vm_vm-14935 + itdps-svactc.nd.gov + + + l_vm_vm-1205 + itdps-dunseith.nd.gov + + + l_vm_vm-907 + itdps-update.nd.gov + + + l_vm_vm-1060 + itdps-edmore.nd.gov + + + l_vm_vm-1110 + itdps-westfarpt.nd.gov + + + l_vm_vm-1044 + itdps-newburg.nd.gov + + + l_vm_vm-1068 + itdps-southhear.nd.gov + + + l_vm_vm-1114 + itdps-northsarg.nd.gov + + + l_vm_vm-1177 + itdps-mayville.nd.gov + + + l_vm_vm-904 + itdps-grandfqa.nd.gov + + + l_vm_vm-1122 + itdps-valleycit.nd.gov + + + l_vm_vm-1197 + itdps-grafton.nd.gov + + + l_vm_vm-1016 + itdps-kensal.nd.gov + + + l_vm_vm-1148 + itdps-northwood.nd.gov + + + l_vm_vm-1012 + itdps-westhope.nd.gov + + + l_vm_vm-1170 + itdps-grandf3.nd.gov + + + l_vm_vm-1087 + itdps-kiddercou.nd.gov + + + l_vm_vm-1126 + itdps-dickin2.nd.gov + + + l_vm_vm-1135 + itdps-rolette.nd.gov + + + l_vm_vm-1153 + itdps-applecree.nd.gov + + + l_vm_vm-1072 + itdps-sawyer.nd.gov + + + l_vm_vm-995 + itdps-stalphons.nd.gov + + + l_vm_vm-1175 + itdps-district8.nd.gov + + + l_vm_vm-1074 + itdps-maplevall.nd.gov + + + l_vm_vm-1128 + itdps-grandfrpt.nd.gov + + + l_vm_vm-1004 + itdps-fourwinds.nd.gov + + + l_vm_vm-1178 + itdps-northbord.nd.gov + + + l_vm_vm-1158 + itdps-minnewauk.nd.gov + + + l_vm_vm-1101 + itdps-cddlc.nd.gov + + + l_vm_vm-1088 + itdps-ndschools.nd.gov + + + l_vm_vm-1164 + itdps-mapleton.nd.gov + + + l_vm_vm-1221 + itdps-mandan1.nd.gov + + + l_vm_vm-14948 + itdps-hettinger.nd.gov + + + l_vm_vm-1005 + itdps-willisdb.nd.gov + + + l_vm_vm-1215 + itdps-hopepage.nd.gov + + + l_vm_vm-1149 + itdps-powerslak.nd.gov + + + l_vm_vm-1113 + itdps-willisrpt.nd.gov + + + l_vm_vm-1216 + itdps-milnor.nd.gov + + + l_vm_vm-1185 + itdps-turtlelak.nd.gov + + + l_vm_vm-1192 + itdps-ditrinity.nd.gov + + + l_vm_vm-1141 + itdps-bismar4.nd.gov + + + l_vm_vm-1162 + itdps-southprai.nd.gov + + + l_vm_vm-1140 + itdps-barnescou.nd.gov + + + l_vm_vm-1104 + itdps-wing.nd.gov + + + l_vm_vm-1057 + itdps-thompson.nd.gov + + + l_vm_vm-1106 + itdps-munich.nd.gov + + + l_vm_vm-1050 + itdps-bottineau.nd.gov + + + l_vm_vm-994 + itdps-hillsboro.nd.gov + + + l_vm_vm-14941 + itdps-sterling.nd.gov + + + l_vm_vm-1089 + itdps-scranton.nd.gov + + + l_vm_vm-1058 + itdps-fessenden.nd.gov + + + l_vm_vm-1203 + itdps-pingreebu.nd.gov + + + l_vm_vm-1100 + itdps-medina.nd.gov + + + l_vm_vm-1027 + itdps-minto.nd.gov + + + l_vm_vm-1001 + itdps-underwood.nd.gov + + + l_vm_vm-1143 + itdps-kindred.nd.gov + + + l_vm_vm-1213 + itdps-velva.nd.gov + + + l_vm_vm-14946 + itdps-fairmount.nd.gov + + + l_vm_vm-1136 + itdps-westfa2.nd.gov + + + l_vm_vm-1146 + itdps-fargo1.nd.gov + + + l_vm_vm-1144 + itdps-lisbon.nd.gov + + + l_vm_vm-998 + itdps-newsalem.nd.gov + + + l_vm_vm-1022 + itdps-stjohn.nd.gov + + + l_vm_vm-1115 + itdps-cavalier.nd.gov + + + l_vm_vm-14932 + itdps-centersta.nd.gov + + + l_vm_vm-1032 + itdps-drayton.nd.gov + + + l_vm_vm-1010 + itdps-richland.nd.gov + + + l_vm_vm-1053 + itdps-fordville.nd.gov + + + l_vm_vm-1073 + itdps-northstar.nd.gov + + + l_vm_vm-14942 + itdps-hankinson.nd.gov + + + l_vm_vm-11739 + itdps-wndctc.nd.gov + + + l_vm_vm-1200 + itdps-linton.nd.gov + + + l_vm_vm-1139 + itdps-westfadb.nd.gov + + + l_vm_vm-13550 + itdps-dakotamem.nd.gov + + + l_vm_vm-1009 + itdps-stmichael.nd.gov + + + l_vm_vm-1093 + itdps-goodrich.nd.gov + + + l_vm_vm-992 + itdps-yellowsto.nd.gov + + + l_vm_vm-1118 + itdps-halliday.nd.gov + + + l_vm_vm-1025 + itdps-stanley.nd.gov + + + l_vm_vm-1214 + itdps-jamestown.nd.gov + + + l_vm_vm-1092 + itdps-killdeer.nd.gov + + + l_vm_vm-1182 + itdps-starkweat.nd.gov + + + l_vm_vm-14939 + itdps-mandan2.nd.gov + + + l_vm_vm-1163 + itdps-wahpeton.nd.gov + + + l_vm_vm-1220 + itdps-fargo3.nd.gov + + + l_vm_vm-1188 + itdps-lidgerwoo.nd.gov + + + l_vm_vm-1091 + itdps-hatton.nd.gov + + + l_vm_vm-1066 + itdps-hmb.nd.gov + + + l_vm_vm-1000 + itdps-midkota.nd.gov + + + l_vm_vm-1086 + itdps-centralca.nd.gov + + + l_vm_vm-1008 + itdps-kenmare.nd.gov + + + l_vm_vm-1043 + itdps-stthomas.nd.gov + + + l_vm_vm-1181 + itdps-glenburn.nd.gov + + + l_vm_vm-1084 + itdps-emerado.nd.gov + + + l_vm_vm-1033 + itdps-anamoosed.nd.gov + + + l_vm_vm-1042 + itdps-images.nd.gov + + + l_vm_vm-1094 + itdps-grenora.nd.gov + + + l_vm_vm-1160 + itdps-roosevelt.nd.gov + + + l_vm_vm-33143 + itdpssandbox1.nd.gov + + + l_vm_vm-1079 + itdps-belfield.nd.gov + + + l_vm_vm-1142 + itdps-minot1.nd.gov + + + l_vm_vm-1193 + itdps-hazen.nd.gov + + + l_vm_vm-1198 + itdps-finleysha.nd.gov + + + l_vm_vm-1041 + itdps-oakes.nd.gov + + + l_vm_vm-1054 + itdps-max.nd.gov + + + l_vm_vm-1121 + itdps-bismar1.nd.gov + + + l_vm_vm-999 + itdps-beulah.nd.gov + + + l_vm_vm-1172 + itdps-orcs.nd.gov + + + l_vm_vm-1187 + itdps-oberon.nd.gov + + + l_vm_vm-1103 + itdps-centralva.nd.gov + + + l_vm_vm-1067 + itdps-deslacsbu.nd.gov + + + l_vm_vm-1138 + itdps-bismar2.nd.gov + + + l_vm_vm-1085 + itdps-minotrpt.nd.gov + + + l_vm_vm-14943 + itdps-ellendale.nd.gov + + + l_vm_vm-1030 + itdps-eightmile.nd.gov + + + l_vm_vm-1048 + itdps-elginnewl.nd.gov + + + l_vm_vm-890 + itdps-testslds.nd.gov + + + l_vm_vm-1055 + itdps-garrison.nd.gov + + + l_vm_vm-1112 + itdps-northvall.nd.gov + + + l_vm_vm-1082 + itdps-stjohnswa.nd.gov + + + l_vm_vm-1117 + itdps-manvel.nd.gov + + + l_vm_vm-1002 + itdps-burkecent.nd.gov + + + l_vm_vm-1190 + itdps-dickinrpt.nd.gov + + + l_vm_vm-1109 + itdps-ndsd.nd.gov + + + l_vm_vm-1137 + itdps-carringto.nd.gov + + + l_vm_vm-1218 + itdps-mandanrpt.nd.gov + + + l_vm_vm-14940 + itdps-richardto.nd.gov + + + l_vm_vm-1155 + itdps-glenullin.nd.gov + + + l_vm_vm-1173 + itdps-minotdb.nd.gov + + + l_vm_vm-1179 + itdps-fargo4.nd.gov + + + l_vm_vm-1020 + itdps-midway.nd.gov + + + l_vm_vm-1015 + itdps-bowbells.nd.gov + + + l_vm_vm-1176 + itdps-mcclusky.nd.gov + + + l_vm_vm-900 + itdps-minottst.nd.gov + + + l_vm_vm-1168 + itdps-grandf1.nd.gov + + + l_vm_vm-1102 + itdps-edgeley.nd.gov + + + l_vm_vm-1040 + itdps-dividecou.nd.gov + + + l_vm_vm-1034 + itdps-alexander.nd.gov + + + l_vm_vm-1125 + itdps-devilslak.nd.gov + + + l_vm_vm-1152 + itdps-larimore.nd.gov + + + l_vm_vm-1169 + itdps-westfa3.nd.gov + + + l_vm_vm-1003 + itdps-kulm.nd.gov + + + l_vm_vm-906 + itdps-mandanqa.nd.gov + + + l_vm_vm-1028 + itdps-bowman.nd.gov + + + l_vm_vm-1119 + itdps-dickin1.nd.gov + + + l_vm_vm-1111 + itdps-nedrose.nd.gov + + + l_vm_vm-1018 + itdps-dakotapra.nd.gov + + + l_vm_vm-1107 + itdps-valleyedi.nd.gov + + + l_vm_vm-1049 + itdps-billingsc.nd.gov + + + l_vm_vm-1078 + itdps-tioga.nd.gov + + + l_vm_vm-997 + itdps-napoleon.nd.gov + + + l_vm_vm-1051 + itdps-mottregen.nd.gov + + + l_vm_vm-1129 + itdps-grandf2.nd.gov + + + l_vm_vm-1206 + itdps-montpelie.nd.gov + + + l_vm_vm-1039 + itdps-maddock.nd.gov + + + l_vm_vm-12921 + itdps-bismarqa.nd.gov + + + l_vm_vm-991 + itdps-ray.nd.gov + + + l_vm_vm-14944 + itdps-gacklestr.nd.gov + + + l_vm_vm-1211 + itdps-leeds.nd.gov + + + l_vm_vm-1081 + itdps-northernc.nd.gov + + + l_vm_vm-1167 + itdps-bismar3.nd.gov + + + l_vm_vm-1069 + itdps-wolford.nd.gov + + + l_vm_vm-1080 + itdps-mtpleasan.nd.gov + + + l_vm_vm-1204 + itdps-lakota.nd.gov + + + l_vm_vm-1017 + itdps-lewisandc.nd.gov + + + l_vm_vm-1105 + itdps-flasher.nd.gov + + + l_vm_vm-1212 + itdps-grandfdb.nd.gov + + + l_vm_vm-20841 + itdps-surrey.nd.gov + + + l_vm_vm-1059 + itdps-watfordci.nd.gov + + + l_vm_vm-1174 + itdps-ashley.nd.gov + + + l_vm_vm-1217 + itdps-minot2.nd.gov + + + l_vm_vm-14947 + itdps-harvey.nd.gov + + + l_vm_vm-996 + itdps-parshall.nd.gov + + + l_vm_vm-14921 + itdps-dickindb.nd.gov + + + l_vm_vm-1191 + itdps-willis1.nd.gov + + + l_vm_vm-901 + itdps-willistst.nd.gov + + + l_vm_vm-1210 + itdps-minot3.nd.gov + + + l_vm_vm-1154 + itdps-willis2.nd.gov + + + l_vm_vm-1024 + itdps-parkriver.nd.gov + + + l_vm_vm-1147 + itdps-mohall.nd.gov + + + l_vm_vm-903 + itdps-fargotst.nd.gov + + + l_vm_vm-1207 + itdps-westfa1.nd.gov + + + l_vm_vm-1108 + itdps-fargorpt.nd.gov + + + l_vm_vm-1019 + itdps-hebron.nd.gov + + + l_vm_vm-14936 + itdps-srctc.nd.gov + + + l_vm_vm-1006 + itdps-langdon.nd.gov + + + l_vm_vm-1099 + itdps-wishek.nd.gov + + + l_vm_vm-11242 + itdps-ftyates.nd.gov + + + l_vm_vm-1201 + itdps-zeeland.nd.gov + + + l_vm_vm-1083 + itdps-litchvill.nd.gov + + + l_vm_vm-1180 + itdps-selfridge.nd.gov + + + l_vm_vm-14945 + itdps-solen.nd.gov + + + l_vm_vm-1183 + itdps-sargentce.nd.gov + + + + l_folder_group-v20450 + Shared-Voice-Avaya-WebConf + + l_vm_vm-1501 + itdbisaac.nd.gov + + + + l_folder_group-v22045 + Shared-Netmotion-Locality + + l_vm_vm-3509 + itdlocality.nd.gov + + + + l_folder_group-v21528 + Shared-HEAT + + l_vm_vm-2429 + itdheatprod1.nd.gov + + + + l_folder_group-v21453 + Shared-EDMS-eForms + + l_vm_vm-2347 + itdeforms.itd.nd.gov + + + + l_folder_group-v20448 + Shared-Voice-Avaya-ECAS + + l_vm_vm-14566 + itdecas2.nd.gov + + + + l_folder_group-v20498 + Shared-MySQL + + l_vm_vm-1931 + itdmysqlprod1.nd.gov + + + l_vm_vm-2054 + itdmysqltest1.nd.gov + + + + l_folder_group-v21525 + Shared-Cognos + + l_vm_vm-3082 + itdcogenttst.nd.gov + + + l_vm_vm-11654 + itdmotio.nd.gov + + + l_vm_vm-2918 + itdcogentprd2.nd.gov + + + l_vm_vm-2382 + itdcogentprd1.nd.gov + + + l_vm_vm-2447 + itdcogentapp.nd.gov + + + l_vm_vm-3319 + itdcog11tst.nd.gov + + + l_vm_vm-3080 + itdcogentpub.nd.gov + + + l_vm_vm-3081 + itdcogentdev.nd.gov + + + + l_folder_group-v20494 + Shared-Apache + + l_vm_vm-2051 + itdapachet1a.nd.gov + + + l_vm_vm-1924 + itdapachep1a.nd.gov + + + l_vm_vm-1925 + itdapachep3.nd.gov + + + + l_folder_group-v22027 + Shared-CrestronFusion + + l_vm_vm-3276 + itdfusion.nd.gov + + + + l_folder_group-v21930 + Shared-Video-Polycomm + + + l_folder_group-v20456 + Shared-Video-vBrick + + l_vm_vm-33084 + itdvbrickrev2.video.nd.gov + + + l_vm_vm-31292 + itdvbrickprxy.video.nd.gov + + + l_vm_vm-1273 + itdvbrickdme1.video.nd.gov + + + l_vm_vm-1288 + itdvbrickdb1.video.nd.gov + + + l_vm_vm-1286 + itdvbrickdme2.video.nd.gov + + + l_vm_vm-1272 + itdvbrickrev.video.nd.gov + + + l_vm_vm-1287 + itdvbrickes1.video.nd.gov + + + + l_folder_group-v22068 + Shared-PowerBI + + l_vm_vm-9427 + itdpbidg.nd.gov + + + + l_folder_group-v22075 + Shared-QMF + + l_vm_vm-15415 + itdqmfp1.nd.gov + + + + l_folder_group-v21450 + Shared-LotusDomino + + l_vm_vm-3017 + nodak04.itd.nd.gov + + + l_vm_vm-3060 + nodak00.itd.nd.gov + + + l_vm_vm-2529 + dhssosrvlnhub.itd.nd.gov + + + l_vm_vm-3411 + nodak02.itd.nd.gov + + + l_vm_vm-41450 + dhssosrvlnapp.itd.nd.gov + + + + l_folder_group-v22093 + Shared-EDMS-SQL + + l_vm_vm-1561 + itdsqledmsp1.nd.gov + + + + l_folder_group-v20451 + Shared-Voice-VoiceMail + + l_vm_vm-27545 + itdaam71storage.nd.gov + + + l_vm_vm-27546 + itdaam71as1.nd.gov + + + + l_folder_group-v20497 + Shared-MasterDataMgt-MCI + + l_vm_vm-43282 + itdmdmprod1.nd.gov + + + l_vm_vm-3229 + itdmciwkbench.itd.nd.gov + + + l_vm_vm-1936 + itdmciprod2.nd.gov + + + l_vm_vm-1945 + itdmciprod.nd.gov + + + l_vm_vm-43283 + itdmdmprod2.nd.gov + + + + l_folder_group-v21595 + Shared-EDMS-FileNet + + l_vm_vm-16866 + itdfnfs3.nd.gov + + + l_vm_vm-1447 + itdfncm3.nd.gov + + + l_vm_vm-1441 + itdfncm4.nd.gov + + + l_vm_vm-16867 + itdfnfs4.nd.gov + + + l_vm_vm-18227 + itdfncc3.nd.gov + + + l_vm_vm-18228 + itdfncc4.nd.gov + + + l_vm_vm-2356 + itdfncn2.nd.gov + + + l_vm_vm-2453 + itdfncn3.nd.gov + + + l_vm_vm-18226 + itdfncse2.nd.gov + + + + l_folder_group-v20499 + Shared-Oracle + + l_vm_vm-2195 + itdoidt2.nd.gov + + + l_vm_vm-2280 + itdoidt1.nd.gov + + + l_vm_vm-1934 + itdoemprod.nd.gov + + + l_vm_vm-2274 + itdoidp1.nd.gov + + + l_vm_vm-45944 + itdoemprod1.nd.gov + + + + l_folder_group-v20500 + Shared-Workforce + + + l_folder_group-v20496 + Shared-Email-Pioneer + + l_vm_vm-1938 + itdpioneer1.state.nd.us + + + + l_folder_group-v20507 + Shared-Email-SecureMail + + + l_folder_group-v21142 + Shared-PeopleSoft-HigherEd + + l_vm_vm-46799 + itdcndhf16sowp.nd.gov + + + l_vm_vm-35386 + itdcndhehy16.nd.gov + + + l_vm_vm-35517 + itdcndhf16wp1.nd.gov + + + l_vm_vm-29742 + itdcndh16es01.nd.gov + + + l_vm_vm-11784 + itdcndhhpdb16.nd.gov + + + l_vm_vm-2454 + itdcndhes02.nd.gov + + + l_vm_vm-29744 + itdcndh16es03.nd.gov + + + l_vm_vm-30911 + itdcndhh16app1.nd.gov + + + l_vm_vm-30908 + itdcndhh16wp1.nd.gov + + + l_vm_vm-35518 + itdcndhf16wp2.nd.gov + + + l_vm_vm-41449 + itdcndhefrdp10.nd.gov + + + l_vm_vm-35385 + itdcndhh16ywt.nd.gov + + + l_vm_vm-31184 + itdcndhh16gw.nd.gov + + + l_vm_vm-35513 + itdcndhf16app1.nd.gov + + + l_vm_vm-2385 + itdcndhebooks1.nd.gov + + + l_vm_vm-29743 + itdcndh16es02.nd.gov + + + l_vm_vm-34996 + itdcndhephip1w.nd.gov + + + l_vm_vm-2570 + itdcndhes03.nd.gov + + + l_vm_vm-30909 + itdcndhh16wp2.nd.gov + + + l_vm_vm-2456 + itdcndheupk1.nd.gov + + + l_vm_vm-23057 + itdcndhfpdb16.nd.gov + + + l_vm_vm-2363 + itdcndhes01.nd.gov + + + l_vm_vm-25882 + itdcndhehrdp7.nd.gov + + + l_vm_vm-35514 + itdcndhf16app2.nd.gov + + + l_vm_vm-2434 + itdcndhehrdp1.nd.gov + + + l_vm_vm-40140 + itdcndhh16cgwp2.nd.gov + + + l_vm_vm-30912 + itdcndhh16app2.nd.gov + + + l_vm_vm-33078 + itdcndhephirew.nd.gov + + + l_vm_vm-40139 + itdcndhh16cgwp1.nd.gov + + + l_vm_vm-34995 + itdcndhephip1.nd.gov + + + l_vm_vm-27453 + itdcndhephire.nd.gov + + + l_vm_vm-30910 + itdcndhh16ps.nd.gov + + + l_vm_vm-2571 + itdcndheurdp1.nd.gov + + + l_vm_vm-35516 + itdcndhf16wp.nd.gov + + + l_vm_vm-30907 + itdcndhh16wp.nd.gov + + + l_vm_vm-35515 + itdcndhf16ps.nd.gov + + + + l_folder_group-v21947 + Shared-CrystalReports + + l_vm_vm-3412 + itdcrystaltest.nd.gov + + + l_vm_vm-3496 + itdcrystalprod.nd.gov + + + + l_folder_group-v21967 + Shared-Andover + + l_vm_vm-41424 + itdandcont2.nd.gov + + + + l_folder_group-v21984 + Shared-WebSphere-CASLogin + + l_vm_vm-2284 + itdcasp1.nd.gov + + + l_vm_vm-2065 + itdcast2.nd.gov + + + l_vm_vm-2068 + itdcasp2.nd.gov + + + l_vm_vm-2075 + itdcast1.nd.gov + + + + l_folder_group-v21387 + Shared-Email-Rightfax + + l_vm_vm-36385 + itdrfax.nd.gov + + + + l_folder_group-v21454 + Shared-EDMS-App + + l_vm_vm-15849 + itdedmsp1.nd.gov + + + + l_folder_group-v21452 + Shared-EDMS-iLINX + + l_vm_vm-2579 + itdilweb1.nd.gov + + + l_vm_vm-2354 + itdilweb2.nd.gov + + + l_vm_vm-19436 + itdilef1.nd.gov + + + l_vm_vm-2459 + itdilem1.nd.gov + + + l_vm_vm-2376 + itdilapp1.nd.gov + + + + + l_folder_group-v21663 + OAH + + + l_folder_group-v21670 + COM + + l_folder_group-v21954 + COM-CRM + + l_vm_vm-3227 + itdcrmp1.nd.gov + + + l_vm_vm-36223 + itdcrmp2.nd.gov + + + + l_folder_group-v22057 + COM-Drupal + + l_vm_vm-2074 + itdnddb1.nd.gov + + + l_vm_vm-2282 + itdndde.nd.gov + + + l_vm_vm-2276 + itdndweb2.nd.gov + + + l_vm_vm-2281 + itdndweb1.nd.gov + + + + + l_folder_group-v21683 + DMR + + + l_folder_group-v21660 + CJIS + + l_folder_group-v21995 + CJIS-WebSphere + + l_vm_vm-2038 + itdcjisws9f1.nd.gov + + + l_vm_vm-1458 + itdcjisws9p2.nd.gov + + + l_vm_vm-1475 + itdcjisws9p1.nd.gov + + + + l_folder_group-v21994 + CJIS-Justware-SQL + + l_vm_vm-3410 + itdcjissqlrep1.nd.gov + + + l_vm_vm-3306 + itdcjissqlp1.nd.gov + + + l_vm_vm-11199 + itdcjissql16p1.nd.gov + + + l_vm_vm-3392 + itdcjissqlt1.nd.gov + + + l_vm_vm-11200 + itdcjissrs16p1.nd.gov + + + + l_folder_group-v21993 + CJIS-Justware + + l_vm_vm-2814 + itdcjisnetp1.nd.gov + + + l_vm_vm-2930 + itdcjisnett1.nd.gov + + + l_vm_vm-12732 + itdcjisnett2.nd.gov + + + + l_folder_group-v22071 + CJIS-LERMS-SQL + + l_vm_vm-3540 + itdpremiersqlp1.nd.gov + + + l_vm_vm-2554 + itdpremiersqlt1.nd.gov + + + l_vm_vm-2961 + itdpremiersqlr1.nd.gov + + + + l_folder_group-v808 + CJIS-LERMS + + l_vm_vm-3136 + itdpremiert1.nd.gov + + + l_vm_vm-3492 + itdpremierp2.nd.gov + + + l_vm_vm-3142 + itdpremierp1.nd.gov + + + + + l_folder_group-v21673 + GNF + + l_folder_group-v22106 + GNF-IIS + + l_vm_vm-2538 + itdwww12.nd.gov + + + + l_folder_group-v20478 + GNF-WebSphere + + l_vm_vm-9150 + itdws9p8.nd.gov + + + l_vm_vm-9149 + itdws9p7.nd.gov + + + l_vm_vm-9148 + itdws9pf2.nd.gov + + + + l_folder_group-v22030 + GNF-GeoComm + + l_vm_vm-2762 + itdgnfgeo1.nd.gov + + + + l_folder_group-v22029 + GNF-Cody + + l_vm_vm-1306 + itdgnfcody2.nd.gov + + + + + l_folder_group-v155 + _Delete Request + + l_vm_vm-3087 + itdcloudnetp1.ndcloud.gov-DLDelete20200701 + + + l_vm_vm-2192 + itddhsnpdmcia01.nd.gov-DLDelete20200701 + + + l_vm_vm-2889 + itddotheat.nd.gov-DLDelete20200630 + + + l_vm_vm-2372 + itdcndsthapp2.nd.gov-DLDelete20200630 + + + l_vm_vm-2567 + itdcndsthapp1.nd.gov-DLDelete20200630 + + + l_vm_vm-2580 + itdcndsthps.nd.gov-DLDelete20200630 + + + l_vm_vm-46614 + itdohrcdbp1.nd.gov-DLDelete20200629 + + + l_vm_vm-1988 + itdmcitest.nd.gov-DLDelete20200701 + + + l_vm_vm-46615 + itdohrcwebp1.nd.gov-DLDelete20200629 + + + l_vm_vm-41453 + itdmfaserver1.nd.gov-DLDelete20200624 + + + + l_folder_group-v156 + _Templates + + l_vm_vm-41336 + EDI Test 02-2019 + + + l_vm_vm-41331 + Windows 10 Enterprise LTSC 2019 + + + l_vm_vm-41333 + Windows Server 2012R2 Standard + + + l_vm_vm-1983 + Red Hat Enterprise Linux - Drupal + + + l_vm_vm-41341 + Windows Server 2012 Standard + + + l_vm_vm-41340 + Windows 10 Enterprise 64Bit LTSB 1607 + + + l_vm_vm-41327 + Red Hat Enterprise Linux - Tomcat + + + l_vm_vm-41324 + Red Hat Enterprise Linux 6 - Master Template + + + l_vm_vm-33080 + PS-Windows 2012R2 Std ORIGINAL + + + l_vm_vm-41337 + itddocemrrdp1_base + + + l_vm_vm-41334 + Windows Server 2016 Standard + + + l_vm_vm-41325 + PS Windows 2012R2 Std 201907 + + + l_vm_vm-1984 + Red Hat Enterprise Linux + + + l_vm_vm-40722 + Windows Server 2019 Standard (Base) + + + l_vm_vm-41343 + Windows Server 2008R2 SP1 Datacenter + + + l_vm_vm-40721 + Windows Server 2019 Standard + + + l_vm_vm-41332 + Windows Server 2012R2 Standard (Base) + + + l_vm_vm-41338 + Windows Server 2016 Standard (Base) + + + l_vm_vm-41342 + Windows 7 SP1 Enterprise + + + l_vm_vm-41335 + Windows Server 2008 SP2 Enterprise (64Bit) + + + l_vm_vm-41339 + Windows - Blank Template + + + + l_folder_group-v21654 + DHS + + l_folder_group-v36850 + DHS-MirrorImage + + l_vm_vm-36793 + itddhsmirrimgp1.nd.gov + + + + l_folder_group-v22008 + DHS-COMPUTRITION + + l_vm_vm-2041 + itddhscompifxp1.nd.gov + + + l_vm_vm-42535 + itddhscompifxp.nd.gov + + + l_vm_vm-1305 + itddhscompprod.nd.gov + + + l_vm_vm-1307 + itddhscomptest.nd.gov + + + + l_folder_group-v21447 + DHS-VISION + + l_vm_vm-3385 + itddlmuat1.nd.gov + + + l_vm_vm-3550 + itdvisioncomp1.nd.gov + + + l_vm_vm-2723 + itddlmdev1.nd.gov + + + l_vm_vm-2870 + itddlmsit1.nd.gov + + + l_vm_vm-3552 + itddlmprtprod.nd.gov + + + l_vm_vm-2813 + itdcse3.nd.gov + + + l_vm_vm-3377 + itdvisioncomt1.nd.gov + + + l_vm_vm-3232 + itddlmtrng1.nd.gov + + + l_vm_vm-2809 + itdvisioncomp2.nd.gov + + + l_vm_vm-2776 + itdblazet2.nd.gov + + + l_vm_vm-3541 + itdblazep1.nd.gov + + + l_vm_vm-3063 + itddlmacpt1.nd.gov + + + l_vm_vm-3307 + itddevw7.nd.gov + + + + l_folder_group-v21390 + DHS-MMIS-MoveIt + + l_vm_vm-2978 + itdmmissqlt1.nd.gov + + + l_vm_vm-3369 + itddhsmidmzp1.mmis.nd.gov + + + l_vm_vm-3555 + itddhsmicenp1.mmis.nd.gov + + + + l_folder_group-v21446 + DHS-PitneyBowes + + l_vm_vm-35630 + itddhspbows1.nd.gov + + + l_vm_vm-3234 + itdpbows1.nd.gov + + + + l_folder_group-v21449 + DHS-Workforce-Windows + + l_vm_vm-2923 + itddhswfrcrptt1.nd.gov + + + l_vm_vm-2971 + itddhswfrcrptp1.nd.gov + + + l_vm_vm-3137 + itddhswfrcp1.nd.gov + + + l_vm_vm-3134 + itddhswfrct1.nd.gov + + + + l_folder_group-v21386 + DHS-Orchard + + l_vm_vm-2935 + itddhshvsthl7.nd.gov + + + l_vm_vm-3478 + itddhsharvestt1.nd.gov + + + l_vm_vm-2780 + itddhsharvestw.nd.gov + + + l_vm_vm-3543 + itddhsharvest.nd.gov + + + + l_folder_group-v24865 + DHS-MMIS-SIM-SAM + + l_vm_vm-24856 + itdprmldap1a.nd.gov + + + l_vm_vm-24864 + itdprmtim3a.nd.gov + + + l_vm_vm-24862 + itdprmtim1a.nd.gov + + + l_vm_vm-24857 + itdprmldap2a.nd.gov + + + l_vm_vm-24861 + itdprmtam3a.nd.gov + + + l_vm_vm-24858 + itdprmldap3a.nd.gov + + + l_vm_vm-24859 + itdprmtam1a.nd.gov + + + l_vm_vm-24863 + itdprmtim2a.nd.gov + + + l_vm_vm-24860 + itdprmtam2a.nd.gov + + + + l_folder_group-v21385 + DHS-OpenScan + + l_vm_vm-3057 + itdopenscan1.itd.nd.gov + + + + l_folder_group-v21955 + DHS-MMIS-Truven-Windows + + l_vm_vm-38699 + itdtrvphrsql1.mmis.nd.gov + + + l_vm_vm-38697 + itdtrvphrgw.mmis.nd.gov + + + l_vm_vm-38698 + itdtrvphrapp1.mmis.nd.gov + + + + l_folder_group-v26945 + DHS-Pyxis + + l_vm_vm-26892 + itddhspyxsecup1.nd.gov + + + l_vm_vm-26891 + itddhspyxesp1.nd.gov + + + l_vm_vm-26890 + itddhspyxccep1.nd.gov + + + + l_folder_group-v21977 + DHS-SPACES-F5 + + l_vm_vm-2061 + itdbdcf5v1.itd.nd.gov + + + l_vm_vm-1864 + itdbdcf5vp1.nd.gov + + + + l_folder_group-v20482 + DHS-CDC + + l_vm_vm-1887 + itdcdcprod.nd.gov + + + l_vm_vm-41618 + itdcdcprod2.nd.gov + + + + l_folder_group-v20483 + DHS-MagiCloud + + l_vm_vm-1890 + itdrails.nd.gov + + + + l_folder_group-v21588 + DHS-MMIS-EDIFECS + + l_vm_vm-25172 + itdeditompxyp1.nd.gov + + + l_vm_vm-25165 + itdedixesrtp1.nd.gov + + + l_vm_vm-25164 + itdedixexesbp1.nd.gov + + + l_vm_vm-18126 + itddhsedifsp1.nd.gov + + + l_vm_vm-25168 + itdedibetls2sp1.nd.gov + + + l_vm_vm-25167 + itdedixecamqp1.nd.gov + + + l_vm_vm-25171 + itdediorels1p1.nd.gov + + + l_vm_vm-25169 + itdediretls3p1.nd.gov + + + l_vm_vm-25173 + itdeditompxyp2.nd.gov + + + l_vm_vm-25170 + itdediappwsp1.nd.gov + + + l_vm_vm-25166 + itdedixesrtp2.nd.gov + + + + l_folder_group-v21391 + DHS-MMIS-Xpressions + + l_vm_vm-2976 + itdprmxpr4.mmis.nd.gov + + + + l_folder_group-v21139 + DHS-Mediclaim + + l_vm_vm-3230 + itdtfdhss2.nd.gov + + + l_vm_vm-3020 + itdtfdhsr2.nd.gov + + + + l_folder_group-v21383 + DHS-AWARE + + + l_folder_group-v21987 + DHS-OWRA + + l_vm_vm-2187 + itdcatp109-178.nd.gov + + + + l_folder_group-v22051 + DHS-MMIS-TMART + + l_vm_vm-3132 + itdmmistmart.nd.gov + + + + l_folder_group-v22003 + DHS-MMIS-Oracle + + + l_folder_group-v21590 + DHS-SPACES + + l_vm_vm-1323 + itddhsdevodma01.nd.gov + + + l_vm_vm-2264 + itddhsdevesba01.nd.gov + + + l_vm_vm-1421 + itddhsprdwasa05.nd.gov + + + l_vm_vm-2177 + itddhsprfwasw02.nd.gov + + + l_vm_vm-1440 + itddhsnpdwasa01.nd.gov + + + l_vm_vm-1885 + itddhsprdrptw01.nd.gov + + + l_vm_vm-1986 + itddhsnpdccma02.nd.gov + + + l_vm_vm-1322 + itddhsprdodma01.nd.gov + + + l_vm_vm-1866 + itddhsprdrptw02.nd.gov + + + l_vm_vm-2184 + itddhsnpdisea01.nd.gov + + + l_vm_vm-1473 + itddhsdevwasa02.nd.gov + + + l_vm_vm-2256 + itddhsnpdbata02.nd.gov + + + l_vm_vm-1884 + itddhsprdccma01.nd.gov + + + l_vm_vm-1880 + itddhsprdsdsd01.nd.gov + + + l_vm_vm-2163 + itddhsdevwasw02.nd.gov + + + l_vm_vm-1457 + itddhsdevwasa01.nd.gov + + + l_vm_vm-1422 + itddhsprdwasa04.nd.gov + + + l_vm_vm-2164 + itddhsnpdesba01.nd.gov + + + l_vm_vm-2058 + itddhssplunkp1.nd.gov + + + l_vm_vm-1455 + itddhsprfwasa06.nd.gov + + + l_vm_vm-1883 + itddhsprdesba01.nd.gov + + + l_vm_vm-1863 + itddhsprdsama01.nd.gov + + + l_vm_vm-1872 + itddhsprdccma02.nd.gov + + + l_vm_vm-1471 + itddhsnpdwasa06.nd.gov + + + l_vm_vm-2167 + itddhsdevsima01.nd.gov + + + l_vm_vm-1882 + itddhsprdbata01.nd.gov + + + l_vm_vm-1874 + itddhsprdissa01.nd.gov + + + l_vm_vm-2039 + itddhsnpdrptw01.nd.gov + + + l_vm_vm-2181 + itddhsnpdwasw04.nd.gov + + + l_vm_vm-1878 + itddhsprdesba02.nd.gov + + + l_vm_vm-1886 + itddhsprdwasw02.nd.gov + + + l_vm_vm-1871 + itddhsprdsima01.nd.gov + + + l_vm_vm-1469 + itddhsprfwasa04.nd.gov + + + l_vm_vm-2140 + itddhsnpdsplnk01.nd.gov + + + l_vm_vm-1456 + itddhsprfwasa01.nd.gov + + + l_vm_vm-1870 + itddhsprdwasw01.nd.gov + + + l_vm_vm-1998 + itddhsdevsama01.nd.gov + + + l_vm_vm-1868 + itddhsprdisea01.nd.gov + + + l_vm_vm-2239 + itddhsnpdsdsd01.nd.gov + + + l_vm_vm-3372 + itddhshpxtrmlic.nd.gov + + + l_vm_vm-2251 + itddhsnpdsama01.nd.gov + + + l_vm_vm-2165 + itddhsdevwasw01.nd.gov + + + l_vm_vm-1881 + itddhsprdsima02.nd.gov + + + l_vm_vm-1320 + itddhsnpdodma01.nd.gov + + + l_vm_vm-1879 + itddhsprdwasw03.nd.gov + + + l_vm_vm-1446 + itddhsprfwasa05.nd.gov + + + l_vm_vm-2073 + itddhsprfwasw01.nd.gov + + + l_vm_vm-1865 + itddhsprdsama02.nd.gov + + + l_vm_vm-1445 + itddhsprfwasa02.nd.gov + + + l_vm_vm-2238 + itddhsnpdsima01.nd.gov + + + l_vm_vm-1876 + itddhsprdwasw04.nd.gov + + + l_vm_vm-2179 + itddhsdevblda02.nd.gov + + + l_vm_vm-1423 + itddhsprdwasa03.nd.gov + + + l_vm_vm-1474 + itddhsnpdwasa02.nd.gov + + + l_vm_vm-2246 + itddhsnpdrpta02.nd.gov + + + l_vm_vm-2071 + itddhsnpdwasw03.nd.gov + + + l_vm_vm-1867 + itddhsprdrpta02.nd.gov + + + l_vm_vm-1873 + itddhsprdbata02.nd.gov + + + l_vm_vm-1443 + itddhsnpdwasa04.nd.gov + + + l_vm_vm-1321 + itddhsprdodma02.nd.gov + + + l_vm_vm-1875 + itddhsprdsdsd02.nd.gov + + + l_vm_vm-2247 + itddhsnpdrpta01.nd.gov + + + l_vm_vm-2291 + itddhsnpdsama02.nd.gov + + + l_vm_vm-2144 + itddhsnpdsplnkidx01.nd.gov + + + l_vm_vm-2158 + itddhsdevblda01.nd.gov + + + l_vm_vm-1995 + itddhsdevcmdb01.nd.gov + + + l_vm_vm-2166 + itddhsdevbata01.nd.gov + + + l_vm_vm-1319 + itddhsprfodma02.nd.gov + + + l_vm_vm-1425 + itddhsprdwasa01.nd.gov + + + l_vm_vm-2178 + itddhsdevsdsd01.nd.gov + + + l_vm_vm-2242 + itddhsnpdesba02.nd.gov + + + l_vm_vm-1470 + itddhsnpdwasa03.nd.gov + + + l_vm_vm-2042 + itddhsdevccma01.nd.gov + + + l_vm_vm-1439 + itddhsnpdwasa05.nd.gov + + + l_vm_vm-2286 + itddhsnpdwasw02.nd.gov + + + l_vm_vm-1325 + itddhsnpdodma02.nd.gov + + + l_vm_vm-1997 + itdsplunkp1.nd.gov + + + l_vm_vm-2180 + itddhsnpdccma01.nd.gov + + + l_vm_vm-10630 + itddhsdevalma01.nd.gov + + + l_vm_vm-2035 + itddhsnpdissm01.nd.gov + + + l_vm_vm-1424 + itddhsprdwasa02.nd.gov + + + l_vm_vm-2267 + itddhsnpdsima02.nd.gov + + + l_vm_vm-1324 + itddhsprfodma01.nd.gov + + + l_vm_vm-1869 + itddhsprdrpta01.nd.gov + + + l_vm_vm-2236 + itddhsnpdsdsd02.nd.gov + + + l_vm_vm-27829 + itddhsnpdslnm02.nd.gov + + + l_vm_vm-3371 + itddhsdevutla01.nd.gov + + + l_vm_vm-2137 + itddhsnpdissa01.nd.gov + + + l_vm_vm-2254 + itddhsnpdwasw01.nd.gov + + + l_vm_vm-2053 + itddhsnpdbata01.nd.gov + + + l_vm_vm-1477 + itddhsprfwasa03.nd.gov + + + l_vm_vm-2295 + itddhsnpdrptw02.nd.gov + + + l_vm_vm-1877 + itddhsprdissm01.nd.gov + + + l_vm_vm-1420 + itddhsprdwasa06.nd.gov + + + + l_folder_group-v22009 + DHS-MMIS-JHD + + l_vm_vm-3364 + itddhsmmisjhd.nd.gov + + + + l_folder_group-v21589 + DHS-MMIS-Truven-Linux + + l_vm_vm-29526 + itdtrvpdb.mmis.nd.gov + + + l_vm_vm-29088 + itdtrvctm.mmis.nd.gov + + + l_vm_vm-2064 + itdtrvds11.nd.gov + + + l_vm_vm-29087 + itdtrvcog.mmis.nd.gov + + + l_vm_vm-29085 + itdtrvgw.mmis.nd.gov + + + l_vm_vm-29089 + itdtrvme.mmis.nd.gov + + + l_vm_vm-29086 + itdtrvsrv.mmis.nd.gov + + + + l_folder_group-v20485 + DHS-MMIS-LoadBalancer + + l_vm_vm-1893 + itdmmisextld1.nd.gov + + + l_vm_vm-1892 + itdmmisldprod.mmis.nd.gov + + + + l_folder_group-v22076 + DHS-Quick + + l_vm_vm-41349 + itdquick.itd.nd.gov + + + + l_folder_group-v20473 + DHS-WebSphere + + l_vm_vm-1414 + itdws9p5.nd.gov + + + l_vm_vm-1380 + itdintws8p5a.nd.gov + + + l_vm_vm-1387 + itdintws9p6.nd.gov + + + l_vm_vm-1386 + itdintws9p5.nd.gov + + + l_vm_vm-1419 + itdws8p6a.nd.gov + + + l_vm_vm-1413 + itdws9p6.nd.gov + + + l_vm_vm-1392 + itdintws8p6a.nd.gov + + + l_vm_vm-1407 + itdws8p5a.nd.gov + + + + l_folder_group-v21929 + DHS-MMIS-ActiveDirectory + + l_vm_vm-37686 + itdsitdc2.sit.mmis.dev + + + l_vm_vm-3494 + itduatdc3.uat.mmis.dev + + + l_vm_vm-14089 + itduatdc4.uat.mmis.dev + + + l_vm_vm-37685 + itdtrndc2.trn.mmis.dev + + + + l_folder_group-v44035 + DHS-BPF + + l_vm_vm-43281 + itddhsbpfcnvp1.nd.gov + + + + l_folder_group-v21928 + DHS-MMIS-RationalReporting + + l_vm_vm-2821 + itdratrpt4.mmis.nd.gov + + + l_vm_vm-3024 + itdratrpt1.mmis.nd.gov + + + l_vm_vm-2765 + itdratrpt3.mmis.nd.gov + + + l_vm_vm-2873 + itdratrpt5.mmis.nd.gov + + + l_vm_vm-2761 + itdratrpt2.mmis.nd.gov + + + + l_folder_group-v22072 + DHS-MMIS-Xpressions-SQL + + l_vm_vm-2718 + itdprmxprsql1.mmis.nd.gov + + + + l_folder_group-v21392 + DHS-MMIS-UC4 + + l_vm_vm-48924 + itddhsuc4p2.nd.gov + + + l_vm_vm-2188 + itddhsuc4t1.mmis.nd.gov + + + l_vm_vm-1891 + itddhsuc4p1.mmis.nd.gov + + + + l_folder_group-v21144 + DHS-QMS + + l_vm_vm-3201 + itddhsqmst1.nd.gov + + + l_vm_vm-2460 + itddhsqmsp1.nd.gov + + + + l_folder_group-v21388 + DHS-MMIS-COGNOS + + l_vm_vm-3472 + itdcogmmistrn.trn.mmis.nd.gov + + + l_vm_vm-2916 + itdcogmmissit.sit.mmis.nd.gov + + + l_vm_vm-3560 + itdcogmmisprm.prm.mmis.nd.gov + + + l_vm_vm-3413 + itdcogmmisprm2.prm.mmis.nd.gov + + + l_vm_vm-2939 + itdcogmmisuat.uat.mmis.nd.gov + + + + l_folder_group-v21143 + DHS-SPACES-EDMS + + l_vm_vm-2560 + itdfncn4.nd.gov + + + + l_folder_group-v21986 + DHS-Entrypoint + + l_vm_vm-2066 + itdcatp109-162.nd.gov + + + + + l_folder_group-v21682 + RIO + + l_folder_group-v21988 + RIO-CPAS + + l_vm_vm-2259 + itdcatp115-18.nd.gov + + + + + l_folder_group-v21679 + DOA + + l_folder_group-v29747 + DOA-Grain-Inspection + + l_vm_vm-36386 + itddoacat1a.nd.gov + + + l_vm_vm-36387 + itddoaintcat1a.nd.gov + + + + + l_folder_group-v21666 + TAX + + l_folder_group-v51788 + TAX-MyQ + + l_vm_vm-51265 + itdtaxmyq.nd.gov + + + + l_folder_group-v22099 + TAX-Teleform + + l_vm_vm-10838 + itdtftax.nd.gov + + + + l_folder_group-v22096 + TAX-ProLaw + + l_vm_vm-9067 + itdtaxappp2.nd.gov + + + + l_folder_group-v22095 + TAX-MirrorImage + + l_vm_vm-2811 + itdtaxappp1.nd.gov + + + + l_folder_group-v818 + TAX-GenTax + + l_vm_vm-45736 + itdtaxpga1.nd.gov + + + l_vm_vm-1546 + itdtaxsql16p1.nd.gov + + + l_vm_vm-34997 + itdtaxpfa1.nd.gov + + + l_vm_vm-45738 + itdtaxpga3.nd.gov + + + l_vm_vm-45742 + itdtaxptw2.nd.gov + + + l_vm_vm-38145 + itdtaxsql19p1.nd.gov + + + l_vm_vm-45739 + itdtaxpta1.nd.gov + + + l_vm_vm-45737 + itdtaxpga2.nd.gov + + + l_vm_vm-45740 + itdtaxpta2.nd.gov + + + l_vm_vm-45741 + itdtaxptw1.nd.gov + + + + + l_folder_group-v21674 + HPN + + l_folder_group-v22034 + HPN-Video + + l_vm_vm-2963 + itdhpnvid.nd.gov + + + + l_folder_group-v22033 + HPN-ProMiles + + l_vm_vm-3085 + itdhpnearp4.nd.gov + + + l_vm_vm-2658 + itdhpnearp2.nd.gov + + + l_vm_vm-2837 + itdhpnearp1.nd.gov + + + l_vm_vm-2959 + itdhpnearp3.nd.gov + + + l_vm_vm-3075 + itdhpneart1.nd.gov + + + + + l_folder_group-v21664 + OMB + + l_folder_group-v22066 + OMB-Print-XeroxOutMgr + + l_vm_vm-2756 + itdoutman1.nd.gov + + + + l_folder_group-v22065 + OMB-WorkRequest + + l_vm_vm-2872 + itdombwr.nd.gov + + + + l_folder_group-v22064 + OMB-RiskVision + + l_vm_vm-3288 + itdombnetp1.nd.gov + + + l_vm_vm-2929 + itdombnett1.nd.gov + + + + l_folder_group-v22001 + OMB-Print-Avanti + + l_vm_vm-3304 + itdcsdavantiprd.nd.gov + + + + l_folder_group-v22063 + OMB-IBARS + + l_vm_vm-2152 + itdombibarsp1.nd.gov + + + l_vm_vm-2153 + itdombibarsp2.nd.gov + + + + + l_folder_group-v21672 + DPI + + l_folder_group-v22025 + DPI-Shared-IIS + + l_vm_vm-51781 + itddpinetp1.nd.gov + + + l_vm_vm-7066 + itddpidev2.nd.gov + + + + l_folder_group-v807 + DPI-SAAR + + l_vm_vm-3366 + itddpisaarp1.nd.gov + + + l_vm_vm-2532 + itddpisaarp2.nd.gov + + + l_vm_vm-49802 + itddpisaarp4.nd.gov + + + l_vm_vm-49801 + itddpisaarp3.nd.gov + + + + + l_folder_group-v21657 + DOT + + l_folder_group-v51785 + DOT-License + + l_vm_vm-48380 + itddotleica.nd.gov + + + + l_folder_group-v22024 + DOT-Workforce-Windows + + l_vm_vm-6127 + itddotwfrct1.nd.gov + + + l_vm_vm-6129 + itddotwfrcp1.nd.gov + + + l_vm_vm-6130 + itddotwfrcrptp1.nd.gov + + + l_vm_vm-6128 + itddotwfrcrptt1.nd.gov + + + + l_folder_group-v22023 + DOT-TFS + + l_vm_vm-2778 + itddottfsp1.nd.gov + + + + l_folder_group-v22022 + DOT-STS + + l_vm_vm-3302 + itddotsts.nd.gov + + + + l_folder_group-v22021 + DOT-HEAT-SQL + + l_vm_vm-1758 + itddotsqlrpt2.nd.gov + + + + l_folder_group-v22019 + DOT-RoadTest + + l_vm_vm-3287 + itddotrtp1.nd.gov + + + + l_folder_group-v22020 + DOT-SCCM + + + l_folder_group-v806 + DOT-STARS + + l_vm_vm-2591 + itddotmvp1.nd.gov + + + l_vm_vm-1571 + itdsqlmvp1.nd.gov + + + l_vm_vm-2364 + itddotmvp2.nd.gov + + + l_vm_vm-2437 + itddotmvp3.nd.gov + + + l_vm_vm-2422 + itddotfcr1.nd.gov + + + + l_folder_group-v37208 + DOT-DTIMS + + l_vm_vm-37203 + itddotdtimsp1.nd.gov + + + + l_folder_group-v21945 + DOT-UNI + + l_vm_vm-3213 + itddotuni4.nd.gov + + + l_vm_vm-3378 + itddotuni3.nd.gov + + + l_vm_vm-2834 + itddotuni1.itd.nd.gov + + + + l_folder_group-v21931 + DOT-FleetFA + + l_vm_vm-2812 + itddotfleett1.nd.gov + + + l_vm_vm-2766 + itddotfleetp1.nd.gov + + + + l_folder_group-v21942 + DOT-DocuSign + + l_vm_vm-21378 + itddotintdsaiis.nd.gov + + + l_vm_vm-19435 + itddotextdsaiis.nd.gov + + + + l_folder_group-v21950 + DOT-Shared-IIS + + l_vm_vm-3513 + itddotnetp1.itd.nd.gov + + + l_vm_vm-3296 + itddotnett1.itd.nd.gov + + + l_vm_vm-41429 + itddotnett2.nd.gov + + + l_vm_vm-22728 + itddotnetep1.nd.gov + + + l_vm_vm-41432 + itddotnetp3.nd.gov + + + + l_folder_group-v22016 + DOT-ATMS + + l_vm_vm-2819 + itddotatmsp1.nd.gov + + + l_vm_vm-3474 + itddotatmsq1.nd.gov + + + + l_folder_group-v21962 + DOT-Shared-App + + l_vm_vm-38696 + itddotserver4.nd.gov + + + l_vm_vm-2964 + dotserver3.nd.gov + + + + l_folder_group-v22017 + DOT-GIS + + l_vm_vm-3486 + itddotgisweb2.nd.gov + + + l_vm_vm-2970 + itddotgis4.nd.gov + + + l_vm_vm-2655 + itddotgisweb.nd.gov + + + l_vm_vm-1742 + itddotgissql1.nd.gov + + + l_vm_vm-34374 + itddotgisweb3.nd.gov + + + l_vm_vm-3133 + itddotgis6.nd.gov + + + l_vm_vm-3027 + itddotgis5.nd.gov + + + + l_folder_group-v22018 + DOT-HEAT + + + + l_folder_group-v21668 + Infra + + l_folder_group-v31667 + Infra-Azure-Build-Linux + + l_vm_vm-31666 + itdlinbuildp1.nd.gov + + + + l_folder_group-v21518 + Infra-Security-AntiVirus-Traps + + l_vm_vm-2587 + itdpaesmext1.nd.gov + + + l_vm_vm-10839 + itdpacloudsync.nd.gov + + + l_vm_vm-2353 + itdpaesmint1.nd.gov + + + + l_folder_group-v21516 + Infra-Networking-Wireless + + l_vm_vm-2458 + itdnps2.nd.gov + + + l_vm_vm-2253 + itdamp.nd.gov + + + l_vm_vm-40213 + itdarubamm1.nd.gov + + + + l_folder_group-v21519 + Infra-Security-CertificateAuthority + + l_vm_vm-2561 + itdcaroot2.nd.gov + + + l_vm_vm-3501 + itdtestdevca7.ndtestdev.nd.dev + + + l_vm_vm-2358 + itdca5.nd.gov + + + l_vm_vm-2465 + itdca6.nd.gov + + + l_vm_vm-3476 + itdtestdevca6.ndtestdev.nd.dev + + + l_vm_vm-3231 + itdtestcaroot1.ndtestdev.nd.dev + + + + l_folder_group-v22107 + Infra-WINS + + l_vm_vm-2531 + ns6.nd.gov + + + + l_folder_group-v22102 + Infra-VMware-DR + + l_vm_vm-35576 + itdvmvra1.nd.gov + + + l_vm_vm-10289 + itdvmvrbp1.nd.gov + + + + l_folder_group-v22007 + Infra-DFS + + l_vm_vm-3394 + itddfsp1.itd.nd.gov + + + l_vm_vm-33424 + itddfsp3.nd.gov + + + + l_folder_group-v22004 + Infra-Networking-Monitoring-Graylog + + l_vm_vm-2252 + itddb-es1.nd.gov + + + l_vm_vm-1981 + itdgraylog3.nd.gov + + + l_vm_vm-2056 + itdgraylog1.nd.gov + + + l_vm_vm-2060 + itdelastic2.nd.gov + + + l_vm_vm-1989 + itdelastic1.nd.gov + + + l_vm_vm-2271 + itdgraylog2.nd.gov + + + l_vm_vm-2279 + itdnetflow1.nd.gov + + + + l_folder_group-v21515 + Infra-MoveIT + + l_vm_vm-5406 + itdmitransferp1.nd.gov + + + l_vm_vm-5405 + itdmigateway.nd.gov + + + l_vm_vm-29308 + itdmiautop1.nd.gov + + + l_vm_vm-2469 + itdmicenp1.nd.gov + + + + l_folder_group-v21998 + Infra-SoftDev-CodeSearch + + l_vm_vm-2597 + itdcodesearch.nd.gov + + + + l_folder_group-v22090 + Infra-Servers-SCCM-SQL + + l_vm_vm-1353 + itdsql16sccm.nd.gov + + + + l_folder_group-v21396 + Infra-SoftDev-TFS + + l_vm_vm-3389 + itdtfst2.itd.nd.gov + + + l_vm_vm-2351 + itdtfsp2.nd.gov + + + l_vm_vm-41455 + itdtfsp3.nd.gov + + + + l_folder_group-v21990 + Infra-SoftDev-ClearCase + + l_vm_vm-2868 + itdcc2.nd.gov + + + + l_folder_group-v21512 + Infra-LicenseMgt-KMS + + l_vm_vm-2582 + itdkms2.nd.gov + + + + l_folder_group-v21981 + Infra-SpectrumProtect-TSMMgr + + + l_folder_group-v21976 + Infra-QA-BeyondCompare + + l_vm_vm-2534 + itdbcompare1.nd.gov + + + + l_folder_group-v22091 + Infra-Monitoring-Solarwinds-SQL + + l_vm_vm-1363 + itdsql16solar.nd.gov + + + + l_folder_group-v21980 + Infra-Storage + + l_vm_vm-25506 + itdibmna1.nd.gov + + + l_vm_vm-12303 + itdbisstghyp1.nd.gov + + + l_vm_vm-12914 + itdbisstgibmdc.nd.gov + + + l_vm_vm-10497 + itdbisstgrpt1.nd.gov + + + + l_folder_group-v21979 + Infra-SpectrumProtect + + l_vm_vm-10626 + itdbisbakoc2.nd.gov + + + + l_folder_group-v21972 + Infra-Azure-ASR + + l_vm_vm-5666 + itdasr2.nd.gov + + + l_vm_vm-5665 + itdasrdp2.nd.gov + + + l_vm_vm-4455 + itdasrdp1.nd.gov + + + l_vm_vm-5584 + itdasr1.nd.gov + + + l_vm_vm-7976 + itdasr2linmt.nd.gov + + + l_vm_vm-7773 + itdasr1linmt.nd.gov + + + + l_folder_group-v22083 + Infra-LogMGT-SecLog + + l_vm_vm-49363 + itdseclogp1.nd.gov + + + l_vm_vm-2249 + itdseclog.nd.gov + + + + l_folder_group-v21966 + Infra-Security-AIP + + l_vm_vm-20236 + itdaipscan1.nd.gov + + + + l_folder_group-v21591 + Infra-Monitoring-Solarwinds + + l_vm_vm-2879 + itdslrwndspoll1.nd.gov + + + l_vm_vm-2721 + itdslrwnds.nd.gov + + + l_vm_vm-2763 + itdslrwndspoll2.nd.gov + + + l_vm_vm-20237 + itdslrwndsbot1.nd.gov + + + + l_folder_group-v20487 + Infra-Email-Relay + + l_vm_vm-1926 + apprelay2.nd.gov + + + l_vm_vm-1927 + apprelay1.nd.gov + + + + l_folder_group-v20502 + Infra-LDAP-TDS + + l_vm_vm-2062 + itdsdst1a.nd.gov + + + l_vm_vm-1959 + itdsdsp1a.nd.gov + + + + l_folder_group-v20493 + Infra-Wiki + + l_vm_vm-1929 + itdwikip1.nd.gov + + + + l_folder_group-v20490 + Infra-Servers-OELR + + l_vm_vm-18822 + itdoraclesatp1.nd.gov + + + + l_folder_group-v33712 + Infra-Monitoring-Assessment + + l_vm_vm-33657 + itdmsanalytics1.nd.gov + + + + l_folder_group-v20503 + Infra-LoadBalancer + + l_vm_vm-1958 + itdintldprod2.nd.gov + + + l_vm_vm-1960 + itdintldprod1.nd.gov + + + + l_folder_group-v22048 + Infra-Security-MFA-SafeNet-Linux + + l_vm_vm-47596 + itdmfa11.nd.gov + + + l_vm_vm-41346 + itdmfa4.nd.gov + + + + l_folder_group-v22043 + Infra-K12-PA + + l_vm_vm-3164 + itdk12paid.k12.nd.us + + + + l_folder_group-v21535 + Infra-Security-MFA-AzureMFA + + l_vm_vm-2425 + itdmfaportal1.nd.gov + + + + l_folder_group-v21996 + Infra-Security-AntiVirus-ClamAV + + l_vm_vm-2241 + itdclamav2.nd.gov + + + l_vm_vm-2183 + itdclamav1.nd.gov + + + + l_folder_group-v21983 + Infra-SoftDev-Jenkins + + l_vm_vm-2131 + itdbuild1.nd.gov + + + + l_folder_group-v22055 + Infra-NetApp + + l_vm_vm-34044 + itdnaum1.nd.gov + + + l_vm_vm-2924 + itdnaom1.itd.nd.gov + + + + l_folder_group-v22101 + Infra-SoftDev-Subversion + + l_vm_vm-2063 + itdvcs.itd.nd.gov + + + + l_folder_group-v22105 + Infra-Desktop-PatchMGT + + l_vm_vm-3408 + itdwsus.nd.gov + + + + l_folder_group-v22082 + Infra-Security-IntelTools + + l_vm_vm-2240 + itdsecintelp1.nd.gov + + + + l_folder_group-v22049 + Infra-Security-MFA-SafeNet-SQL + + l_vm_vm-1740 + itdmfasql1.nd.gov + + + l_vm_vm-34998 + itdmfasql16p1.nd.gov + + + + l_folder_group-v20506 + Infra-SKLM + + l_vm_vm-1948 + itdbissklm1.nd.gov + + + + l_folder_group-v21939 + Infra-SpectrumProtect-VE + + l_vm_vm-36556 + itdvmvc1spvcli.nd.gov + + + l_vm_vm-2642 + itdvmvcp1-linmp.nd.gov + + + l_vm_vm-3008 + itdvmvcp1-winmp.nd.gov + + + l_vm_vm-36557 + itdvmvc1spdm01.nd.gov + + + + l_folder_group-v22088 + Infra-LogMGT-Splunk + + l_vm_vm-2146 + itdsplunkidxp01.nd.gov + + + l_vm_vm-1978 + itdsplunkidxt01.nd.gov + + + + l_folder_group-v21971 + Infra-QA-ScanTools-AppScan + + l_vm_vm-41418 + itdappscan01.nd.gov + + + + l_folder_group-v45629 + Infra-Networking-Algosec + + + l_folder_group-v21965 + Infra-Security-ADTasks + + l_vm_vm-43968 + itdsecurity1.nd.gov + + + l_vm_vm-19864 + itdadsp1.nd.gov + + + + l_folder_group-v21534 + Infra-ADFS-DirSync + + l_vm_vm-5664 + itddsync2.nd.gov + + + l_vm_vm-2592 + itddsync1.nd.gov + + + l_vm_vm-21832 + itddsynct1.testnd.gov + + + + l_folder_group-v21511 + Infra-Desktop-Encryption + + l_vm_vm-2378 + itdmbam1.nd.gov + + + + l_folder_group-v21536 + Infra-Security-MFA-SafeNet + + l_vm_vm-36794 + itdmfavpnagent1.nd.gov + + + l_vm_vm-2652 + itdmfa1.nd.gov + + + l_vm_vm-2359 + itdmfa3.nd.gov + + + l_vm_vm-36795 + itdmfavpnagent2.nd.gov + + + + l_folder_group-v20491 + Infra-Servers-Satellite + + l_vm_vm-45630 + itdsatellite1.nd.gov + + + l_vm_vm-1939 + itdsatellitep1.nd.gov + + + + l_folder_group-v21941 + Infra-ActiveDirectory + + l_vm_vm-2643 + itdtestdevdc2.ndtestdev.nd.dev + + + l_vm_vm-17509 + itddc18.nd.gov + + + l_vm_vm-2594 + itdresdc3.ndcloud.gov + + + l_vm_vm-3300 + itdtestdevdc1.ndtestdev.nd.dev + + + l_vm_vm-21830 + itddct3.testnd.gov + + + l_vm_vm-2593 + itdresdc4.ndcloud.gov + + + l_vm_vm-2886 + itdtestresdc2.test.ndcloud.gov + + + + l_folder_group-v45729 + Infra-Graylog + + l_vm_vm-45757 + itdgrafanap1.nd.gov + + + l_vm_vm-45697 + itdgraylogp3.nd.gov + + + l_vm_vm-45696 + itdgraylogp2.nd.gov + + + l_vm_vm-45755 + itdfluentp3.nd.gov + + + l_vm_vm-45677 + itdgraylogp1.nd.gov + + + l_vm_vm-45678 + itdelasticp4.nd.gov + + + l_vm_vm-45695 + itdelasticp2.nd.gov + + + l_vm_vm-45753 + itdfluentp1.nd.gov + + + l_vm_vm-45756 + itdpromp1.nd.gov + + + l_vm_vm-45694 + itdelasticp1.nd.gov + + + l_vm_vm-45754 + itdfluentp2.nd.gov + + + l_vm_vm-45693 + itdelasticp3.nd.gov + + + + l_folder_group-v22050 + Infra-Security-MineMeld + + l_vm_vm-2275 + itdminemeld.nd.gov + + + + l_folder_group-v21592 + Infra-Servers-SCCM + + l_vm_vm-1570 + itdsccmp2rsp.nd.gov + + + l_vm_vm-2423 + itdsccmp2.nd.gov + + + + l_folder_group-v31990 + Infra-Security-DVR + + l_vm_vm-31989 + itddvrp1.nd.gov + + + + l_folder_group-v22058 + Infra-Security-ScanTools-Nessus + + l_vm_vm-29470 + itdtsc.nd.gov + + + l_vm_vm-49301 + itdnessus3.nd.gov + + + l_vm_vm-28019 + itdnessus2.nd.gov + + + l_vm_vm-2159 + itdnessus.itd.nd.gov + + + + l_folder_group-v22035 + Infra-F5 + + l_vm_vm-2091 + itdbdcf5vt1.nd.gov + + + l_vm_vm-33483 + itdf5sharedt1.nd.gov + + + + l_folder_group-v22098 + Infra-SoftDev-TFS-SP + + l_vm_vm-3388 + itdtfsspprod.nd.gov + + + + l_folder_group-v20464 + Infra-PasswordState + + l_vm_vm-1350 + itdapv.nd.gov + + + l_vm_vm-19963 + itdpv2.nd.gov + + + + l_folder_group-v22062 + Infra-MSOffice + + + l_folder_group-v51787 + Infra-Monitoring-Storage + + l_vm_vm-51022 + itdstgfluentp1.nd.gov + + + + l_folder_group-v41524 + Infra-Servers-WindowsAdmin + + l_vm_vm-41435 + itdwacp1.nd.gov + + + + l_folder_group-v32916 + Infra-SoftDev-Misc + + l_vm_vm-2147 + itdskunkworx.nd.gov + + + + l_folder_group-v22069 + Infra-Networking-VPN + + l_vm_vm-41433 + itdnps3.nd.gov + + + l_vm_vm-2151 + itd-pcs-sslvpn-vapp1.nd.gov + + + + l_folder_group-v22056 + Infra-Networking-NetBrain + + + l_folder_group-v35163 + Infra-Servers-Linux-Baselines + + l_vm_vm-35162 + itdciscat.nd.gov + + + + l_folder_group-v22060 + Infra-Networking-SpeedTest + + + l_folder_group-v28221 + Infra-PTA + + + l_folder_group-v20488 + Infra-LogMGT-Logstash + + + l_folder_group-v20505 + Infra-Proxy + + l_vm_vm-2089 + itdextldprod2.nd.gov + + + l_vm_vm-45752 + itdintrpmgrp1.nd.gov + + + l_vm_vm-1953 + itdextrp3.nd.gov + + + l_vm_vm-1947 + itdegressrp1.nd.gov + + + l_vm_vm-1956 + itdintrp1.nd.gov + + + l_vm_vm-1955 + itdextrp1.nd.gov + + + l_vm_vm-1961 + itdextrp2.nd.gov + + + l_vm_vm-7974 + itdextrp10.nd.gov + + + l_vm_vm-7972 + itdextrp9.nd.gov + + + l_vm_vm-2088 + itdextldprod1.nd.gov + + + l_vm_vm-2090 + itdextrp7.nd.gov + + + l_vm_vm-1951 + itdextrp4.nd.gov + + + l_vm_vm-2297 + itdextldprod3.nd.gov + + + l_vm_vm-2298 + itdextrp8.nd.gov + + + l_vm_vm-1954 + itdextrp6.nd.gov + + + l_vm_vm-1952 + itdextrp5.nd.gov + + + + l_folder_group-v20492 + Infra-UC4 + + l_vm_vm-15366 + itduc4p1.itd.nd.gov + + + l_vm_vm-2076 + itduc4t1.itd.nd.gov + + + + l_folder_group-v20489 + Infra-Servers-Ansible + + l_vm_vm-7637 + itdansible.nd.gov + + + l_vm_vm-2168 + itdgitlab.nd.gov + + + + l_folder_group-v20504 + Infra-OneView + + l_vm_vm-1957 + itdoneviewp1.nd.gov + + + l_vm_vm-2243 + itdoneviewt1.nd.gov + + + + l_folder_group-v34614 + Infra-Security-Demisto + + l_vm_vm-34611 + itddemistoeip1.nd.gov + + + + l_folder_group-v21978 + Infra-LicenseMGT-IBM + + l_vm_vm-10495 + itdbigfix.nd.gov + + + + l_folder_group-v21940 + Infra-VMware + + l_vm_vm-2865 + itdvmvraiaasp1.nd.gov + + + l_vm_vm-3498 + itdvmbackups.nd.gov + + + l_vm_vm-25159 + itdvmvcp1script.nd.gov + + + l_vm_vm-42348 + itdvmvc1.nd.gov + + + l_vm_vm-16215 + itdvmutil.nd.gov + + + l_vm_vm-822 + itdvmsrm1.nd.gov + + + l_vm_vm-10049 + itdvmvrautop1.nd.gov + + + l_vm_vm-2182 + itdbisvma.nd.gov + + + l_vm_vm-3376 + itdvmomp1.nd.gov + + + l_vm_vm-2541 + itdvmconvert.nd.gov + + + + l_folder_group-v21517 + Infra-Print + + l_vm_vm-12730 + itdprint1e.nd.gov + + + l_vm_vm-2421 + itdprint1d.nd.gov + + + l_vm_vm-25738 + itdprint1tst.nd.gov + + + l_vm_vm-12393 + itdprint1f.nd.gov + + + l_vm_vm-12304 + itdprint1g.nd.gov + + + l_vm_vm-2381 + itdprint2a.nd.gov + + + l_vm_vm-12305 + itdprint1h.nd.gov + + + + l_folder_group-v45730 + Infra-NDLoginProxy + + l_vm_vm-45732 + itdb2cpxyp2.nd.gov + + + l_vm_vm-45731 + itdb2cpxyp1.nd.gov + + + + l_folder_group-v34047 + Infra-Security-Pathfinder + + l_vm_vm-34046 + itdpapathfinder.nd.gov + + + + l_folder_group-v21974 + Infra-Storage-AWSGateway + + l_vm_vm-10257 + itdawsstorp.nd.gov + + + + l_folder_group-v20501 + Infra-ADFS + + l_vm_vm-12738 + itdadfspxy4.nd.gov + + + l_vm_vm-21833 + itdadfspxyt5.testnd.gov + + + l_vm_vm-12735 + itdadfs3.nd.gov + + + l_vm_vm-1950 + itdadfsintldp1.nd.gov + + + l_vm_vm-1949 + itdadfsldp1.nd.gov + + + l_vm_vm-21831 + itdadfst5.testnd.gov + + + l_vm_vm-12736 + itdadfs4.nd.gov + + + l_vm_vm-12737 + itdadfspxy3.nd.gov + + + + l_folder_group-v21513 + Infra-LicenseMgt-Misc + + l_vm_vm-2435 + itdkms1.nd.gov + + + + l_folder_group-v21973 + Infra-Security-Audit + + l_vm_vm-2979 + itdaudit1.nd.gov + + + + l_folder_group-v21964 + Infra-MSLDS-AddressBook + + l_vm_vm-3298 + itdadldsp1.nd.gov + + + + l_folder_group-v22081 + Infra-Search + + l_vm_vm-17779 + itdsearchbloxp1.nd.gov + + + + + l_folder_group-v21680 + PNR + + l_folder_group-v22070 + PNR-POS + + + + l_folder_group-v39291 + _New Builds + + l_vm_vm-50479 + itdzmbuild01.nd.gov + + + + l_folder_group-v21662 + LCN + + l_folder_group-v21943 + LCN-LEGEND-RND + + l_vm_vm-3776 + itdrnd1a.legend.nd.gov + + + l_vm_vm-3777 + itdrnd2a.legend.nd.gov + + + l_vm_vm-2757 + itdrnd1.sit.legend.nd.gov + + + + l_folder_group-v21594 + LCN-LEGEND + + l_vm_vm-14474 + itdrdblegend.nd.gov + + + l_vm_vm-2069 + itdmgmt.legend.nd.gov + + + l_vm_vm-14473 + itdpublegend.nd.gov + + + l_vm_vm-14471 + itdapplegend.nd.gov + + + l_vm_vm-1900 + itdrdb.legend.nd.gov + + + l_vm_vm-14472 + itdpglegend.nd.gov + + + + + l_folder_group-v21677 + SHS + + l_folder_group-v22085 + SHS-Preservica + + l_vm_vm-36168 + itdshspresrvt1.nd.gov + + + l_vm_vm-3198 + itdshspresrvp1.nd.gov + + + + l_folder_group-v22084 + SHS-Shared-App + + l_vm_vm-2913 + itdshsapps.nd.gov + + + + + l_folder_group-v21675 + JSN + + l_folder_group-v21970 + JSN-Stealthbits + + l_vm_vm-14476 + itdapp12.nd.gov + + + + l_folder_group-v814 + JSN-UIAA + + l_vm_vm-2885 + itdjsnuip1.nd.gov + + + l_vm_vm-46363 + itdjsnuip1b.nd.gov + + + l_vm_vm-45721 + itdjsnrdsp1.nd.gov + + + + l_folder_group-v22038 + JSN-EOM + + l_vm_vm-33990 + itdjsneomp1.nd.gov + + + + l_folder_group-v22037 + JSN-IBIQ + + l_vm_vm-33987 + itdjsnibiqp1.nd.gov + + + + l_folder_group-v22039 + JSN-MainframeConsole + + l_vm_vm-19866 + itdjsnldapc.nd.gov + + + + l_folder_group-v22036 + JSN-EAE + + l_vm_vm-3480 + itdjsnabsuitep1.nd.gov + + + l_vm_vm-39789 + itdjsnabsuitep2.nd.gov + + + + l_folder_group-v49725 + JSN-UIICE + + l_vm_vm-47036 + itdjsnuip1c.nd.gov + + + + l_folder_group-v50963 + JSN-SecurityIncident + + l_vm_vm-50961 + itdjsnmfdb.nd.gov + + + + + l_folder_group-v21655 + DOC + + l_folder_group-v35900 + DOC-InmateEd + + l_vm_vm-46552 + itddocrlib1.nd.gov + + + l_vm_vm-46551 + itddocrctxlib.nd.gov + + + + l_folder_group-v22013 + DOC-RDS + + l_vm_vm-3210 + itddocrrds.nd.gov + + + + l_folder_group-v22011 + DOC-Compass + + l_vm_vm-3156 + itddocnetp1.nd.gov + + + l_vm_vm-3204 + itddocnett1.nd.gov + + + + l_folder_group-v22010 + DOC-EMRApp + + l_vm_vm-3381 + itddocappp1.itd.nd.gov + + + l_vm_vm-2881 + itddocappp2.itd.nd.gov + + + l_vm_vm-30220 + itddocemrrdp1.nd.gov + + + + l_folder_group-v22012 + DOC-CIPS + + l_vm_vm-3023 + itddocrcips.nd.gov + + + + l_folder_group-v22002 + DOC-FilePrint + + l_vm_vm-3090 + itddata50a.nd.gov + + + + + l_folder_group-v21681 + PSC + + l_folder_group-v22073 + PSC-Tomcat + + l_vm_vm-2139 + itdpsccat1.nd.gov + + + + + l_folder_group-v21658 + ERN + + l_folder_group-v21147 + ERN-PERSLink + + l_vm_vm-3158 + itdernsag4.nd.gov + + + l_vm_vm-2449 + itdernsag8.nd.gov + + + l_vm_vm-3318 + itdernsag7.nd.gov + + + l_vm_vm-3202 + itdernsag6.nd.gov + + + l_vm_vm-3404 + itdernsag9.nd.gov + + + l_vm_vm-3009 + itdernsag5.nd.gov + + + l_vm_vm-3539 + itdernsag3.nd.gov + + + + l_folder_group-v21537 + ERN-PERSLink-Mobile + + l_vm_vm-2922 + itdernsag12.nd.gov + + + l_vm_vm-3493 + itdernsag13.nd.gov + + + l_vm_vm-2925 + itdernsag10.nd.gov + + + + + l_folder_group-v21661 + ITD + + l_folder_group-v21522 + ITD-GIS-HUB + + l_vm_vm-2583 + itdgisags3.nd.gov + + + l_vm_vm-3471 + itdgisfme4.nd.gov + + + l_vm_vm-2645 + itdgisags5.nd.gov + + + l_vm_vm-3211 + itdgisags4.nd.gov + + + l_vm_vm-2927 + itdgisags2.nd.gov + + + l_vm_vm-41456 + itdgisutility.nd.gov + + + l_vm_vm-3508 + itdgisfme5.nd.gov + + + l_vm_vm-3217 + itdgisags1.nd.gov + + + l_vm_vm-3127 + itdgisags6.nd.gov + + + + l_folder_group-v22092 + ITD-Reporting-DataMart + + l_vm_vm-1544 + itdsql17rasbt1.nd.gov + + + + l_folder_group-v21997 + ITD-SLDS-dotNET + + l_vm_vm-30913 + itdcloudnetp3.ndcloud.gov + + + l_vm_vm-28907 + itdcloudnetp2.ndcloud.gov + + + l_vm_vm-30914 + itdcloudnettrn1.ndcloud.gov + + + + l_folder_group-v21991 + ITD-CDE-CMS + + l_vm_vm-3222 + itdcdeweb.nd.gov + + + + l_folder_group-v22494 + ITD-POC-Linux + + l_vm_vm-23440 + itdrh7conftst.nd.gov + + + + l_folder_group-v22087 + ITD-SLDS + + l_vm_vm-3487 + itdsledd1he.ndcloud.gov + + + l_vm_vm-30802 + itdsledsqltrnp.ndcloud.gov + + + l_vm_vm-3456 + itdsledqa1.ndcloud.gov + + + l_vm_vm-3510 + itdsqlspsldsdev.k12tst.nd.us + + + l_vm_vm-1741 + itdsledrasp1.ndcloud.gov + + + l_vm_vm-2725 + itdsqlspsldsp1.k12.nd.us + + + l_vm_vm-2716 + itdsledd1k12.ndcloud.gov + + + + l_folder_group-v22031 + ITD-Reporting + + + l_folder_group-v21949 + ITD-POC-Security + + + l_folder_group-v21593 + ITD-Workforce + + l_vm_vm-12915 + itdwfrcrptp1.nd.gov + + + l_vm_vm-34207 + itdwfrcrptp2.nd.gov + + + l_vm_vm-12916 + itdwfrcp1.nd.gov + + + + l_folder_group-v29532 + ITD-GIS-HUB-SQL + + l_vm_vm-29530 + itdsql17gisp1.nd.gov + + + + l_folder_group-v22046 + ITD-MagicInfo + + + l_folder_group-v28020 + ITD-SLDS-PowerBI + + l_vm_vm-27929 + itdsldspbidg1.ndcloud.gov + + + + l_folder_group-v22006 + ITD-POC-SoftDev + + + l_folder_group-v49546 + ITD-FilePrint + + l_vm_vm-49364 + itdfs1.nd.gov + + + + l_folder_group-v21953 + ITD-SLDS-SharePoint + + l_vm_vm-9641 + itdsldsspprod2.ndcloud.gov + + + l_vm_vm-3209 + itdsldsspprod1.ndcloud.gov + + + l_vm_vm-3162 + itdspdevk12tst.k12tst.nd.us + + + l_vm_vm-3489 + itdspsldsprod.k12.nd.us + + + + l_folder_group-v23871 + ITD-POC-Desktop + + l_vm_vm-24056 + itdsccm1report.nd.gov + + + + l_folder_group-v21952 + ITD-SLDS-Attunity + + l_vm_vm-3275 + itdsldattprd1.ndcloud.gov + + + l_vm_vm-3028 + itdsldatttst1.ndcloud.gov + + + + l_folder_group-v22054 + ITD-POC-IIS + + l_vm_vm-3403 + itdnanfstest.nd.gov + + + + l_folder_group-v22053 + ITD-DefendX + + l_vm_vm-12122 + itdnadefendp1.nd.gov + + + + l_folder_group-v22061 + ITD-POC-Networking + + l_vm_vm-28391 + itdnsalgosec.nd.gov + + + l_vm_vm-2196 + itdtufin.nd.gov + + + l_vm_vm-24715 + itd-ac-sbc1.nd.gov + + + + l_folder_group-v22080 + ITD-POC-Tier2 + + + l_folder_group-v22074 + ITD-BI-PowerDesigner + + l_vm_vm-11653 + itdpwrdsg.nd.gov + + + + l_folder_group-v22042 + ITD-EDUTech-K12FIM-SQL + + l_vm_vm-2646 + itdk12fimsqls1.stg.k12.nd.us + + + l_vm_vm-3561 + itdk12fimsql1.k12.nd.us + + + + l_folder_group-v22040 + ITD-EDUTech-K12FIM + + l_vm_vm-2272 + itdk12adfsintld.stg.k12.nd.us + + + l_vm_vm-3399 + itdk12adfspxys2.stg.k12.nd.us + + + l_vm_vm-2530 + itdk12adfspxys1.stg.k12.nd.us + + + l_vm_vm-2810 + itdk12adfs3.k12.nd.us + + + l_vm_vm-3152 + itdk12adfss2.stg.k12.nd.us + + + l_vm_vm-2884 + itdk12adfspxy3.k12.nd.us + + + l_vm_vm-3220 + itdk12fimsyncs1.stg.k12.nd.us + + + l_vm_vm-2134 + itdk12adfsintldp1.k12.nd.us + + + l_vm_vm-3497 + itdk12adfs2.k12.nd.us + + + l_vm_vm-2194 + itdk12adfsldp1.k12.nd.us + + + l_vm_vm-3146 + itdk12fimsync1.k12.nd.us + + + l_vm_vm-2724 + itdk12fimptls1.stg.k12.nd.us + + + l_vm_vm-3390 + itdk12adfsproxy.k12.nd.us + + + l_vm_vm-2135 + itdk12adfsld.stg.k12.nd.us + + + l_vm_vm-2977 + itdk12dsync2.k12.nd.us + + + l_vm_vm-3058 + itdk12stgdsync2.stg.k12.nd.us + + + l_vm_vm-2653 + itdk12fimptl1.k12.nd.us + + + l_vm_vm-3226 + itdk12fimptls2.stg.k12.nd.us + + + l_vm_vm-3312 + itdk12adfss1.stg.k12.nd.us + + + l_vm_vm-3069 + itdk12adfsd1.k12tst.nd.us + + + l_vm_vm-2779 + itdk12fimptl2.k12.nd.us + + + l_vm_vm-3015 + itdk12adfspxy2.k12.nd.us + + + + l_folder_group-v22044 + ITD-Desktop-Inventory + + l_vm_vm-3078 + itdlansweeper.nd.gov + + + + l_folder_group-v22052 + ITD-POC-BI + + + l_folder_group-v21963 + ITD-Andover + + l_vm_vm-3477 + itdaccess2.nd.gov + + + + l_folder_group-v21975 + ITD-POC-Architecture + + l_vm_vm-8174 + itdazmig4.nd.gov + + + l_vm_vm-2960 + itdstratop1.nd.gov + + + l_vm_vm-6005 + itdazmig2.nd.gov + + + l_vm_vm-6006 + itdazmig3.nd.gov + + + l_vm_vm-3324 + itdstratop2.nd.gov + + + l_vm_vm-6004 + itdazmig1.nd.gov + + + + l_folder_group-v22086 + ITD-SLDS-MLDE + + l_vm_vm-3200 + itdsldsmlde.ndcloud.gov + + + + + l_folder_group-v21678 + WSI + + l_folder_group-v20467 + WSI-Reporting + + l_vm_vm-1366 + itdwsisqlsasp1.nd.gov + + + l_vm_vm-1365 + itdwsisqlsrsp1.nd.gov + + + l_vm_vm-25412 + itdwsisqlsrxp1.nd.gov + + + + l_folder_group-v21234 + WSI-Extranet + + l_vm_vm-39094 + itdwsiextdevops.nd.gov + + + l_vm_vm-38701 + itdwsiextappc2.nd.gov + + + l_vm_vm-38700 + itdwsiextappc1.nd.gov + + + l_vm_vm-26160 + itdwsiextmgmtp1.nd.gov + + + l_vm_vm-4544 + itdwsiextsrvt1.nd.gov + + + l_vm_vm-2552 + itdwsiextappp2.nd.gov + + + l_vm_vm-3325 + itdwsiextappd1.nd.gov + + + l_vm_vm-4545 + itdwsiextsrvp1.nd.gov + + + l_vm_vm-3546 + itdwsiextappp1.nd.gov + + + + l_folder_group-v22103 + WSI-Extranet-SQL + + l_vm_vm-1580 + itdwsiextsqlp2.nd.gov + + + l_vm_vm-1573 + itdwsiextsqlp1.nd.gov + + + + l_folder_group-v21229 + WSI-Shared-App + + l_vm_vm-3537 + wsiapp1.itd.nd.gov + + + + l_folder_group-v21148 + WSI-CAPS + + l_vm_vm-3362 + itdwsitestuat01.nd.gov + + + l_vm_vm-3149 + itdwsitestdevr1.nd.gov + + + l_vm_vm-3479 + itdwsitestdevm1.nd.gov + + + l_vm_vm-2815 + itdwsiprdweb01.nd.gov + + + l_vm_vm-3165 + itdwsitestsys01.nd.gov + + + l_vm_vm-3139 + itdwsitestscr01.nd.gov + + + l_vm_vm-2882 + itdwsitestcert1.nd.gov + + + + l_folder_group-v21226 + WSI-Forms + + + l_folder_group-v22100 + WSI-Mediclaim + + + l_folder_group-v21228 + WSI-Oracle-Reports + + l_vm_vm-3291 + wsireports.nd.gov + + + + l_folder_group-v22104 + WSI-dotNet + + l_vm_vm-41431 + itdwsinett2.nd.gov + + + l_vm_vm-3014 + itdwsinett1.nd.gov + + + l_vm_vm-41428 + itdwsinetp1.nd.gov + + + + l_folder_group-v21236 + WSI-PitneyBowes + + l_vm_vm-33988 + itdwsipb2.nd.gov + + + + l_folder_group-v21227 + WSI-ITSM + + l_vm_vm-3021 + itdwsiitsm.nd.gov + + + + + l_folder_group-v21676 + RRI + + l_folder_group-v22079 + RRI-Macola + + l_vm_vm-2654 + itdrrisynergy.nd.gov + + + l_vm_vm-2824 + itdrriessql.nd.gov + + + + + + l_folder_group-h4 + host + + l_computeResource_domain-c115 + WAS1 + + l_host_host-1369 + itdbisvm-was01.nd.gov + + + l_host_host-1398 + itdbisvm-was02.nd.gov + + + l_host_host-1462 + itdappvm123.nd.gov + + + l_host_host-1433 + itdappvm122.nd.gov + + + l_host_host-15943 + itdbisvm-was03.nd.gov + + + l_resource_resgroup-116 + Resources + + + + l_computeResource_domain-c113 + TEL1 + + l_host_host-1243 + itdbisvm-tel04.nd.gov + + + l_host_host-16874 + itdbisvm-tel07.nd.gov + + + l_host_host-1254 + itdbisvm-tel03.nd.gov + + + l_host_host-1276 + itdbisvm-tel02.nd.gov + + + l_host_host-9347 + itdbisvm-tel05.nd.gov + + + l_host_host-1284 + itdbisvm-tel06.nd.gov + + + l_resource_resgroup-114 + Resources + + + + l_computeResource_domain-c111 + SQL1 + + l_host_host-1356 + itdappvm118.nd.gov + + + l_host_host-1564 + itdbisvm-sql02.nd.gov + + + l_host_host-1744 + itdbisvm-sql05.nd.gov + + + l_host_host-1548 + itdappvm120.nd.gov + + + l_host_host-1551 + itdappvm126.nd.gov + + + l_host_host-1539 + itdappvm119.nd.gov + + + l_host_host-1558 + itdbisvm-sql01.nd.gov + + + l_host_host-1574 + itdbisvm-sql03.nd.gov + + + l_host_host-1332 + itdappvm117.nd.gov + + + l_host_host-1735 + itdbisvm-sql04.nd.gov + + + l_host_host-1751 + itdbisvm-sql06.nd.gov + + + l_resource_resgroup-112 + Resources + + + + l_computeResource_domain-c105 + ODM1 + + l_host_host-20292 + itdbisvm-odm01.nd.gov + + + l_host_host-1329 + itdbisvm-odm02.nd.gov + + + l_resource_resgroup-106 + Resources + + + + l_computeResource_domain-c81 + WINDOWS1 + + l_host_host-3516 + itdbisvm-win05.nd.gov + + + l_host_host-2693 + itdappvm138.nd.gov + + + l_host_host-3238 + itdbisvm-win02.nd.gov + + + l_host_host-2783 + itdappvm142.nd.gov + + + l_host_host-2731 + itdappvm140.nd.gov + + + l_host_host-2324 + itdbisvm-win06.nd.gov + + + l_host_host-2388 + itdbisvm-gen05.nd.gov + + + l_host_host-3416 + itdbisvm-win04.nd.gov + + + l_host_host-15783 + itdappvm144.nd.gov + + + l_host_host-3169 + itdbisvm-gen07.nd.gov + + + l_host_host-3094 + itdbisvm-gen06.nd.gov + + + l_host_host-3032 + itdappvm147.nd.gov + + + l_host_host-2840 + itdappvm143.nd.gov + + + l_host_host-15787 + itdappvm145.nd.gov + + + l_host_host-2478 + itdbisvm-win01.nd.gov + + + l_host_host-2982 + itdappvm146.nd.gov + + + l_host_host-2623 + itdappvm141.nd.gov + + + l_host_host-3329 + itdbisvm-win03.nd.gov + + + l_host_host-7187 + itdappvm139.nd.gov + + + l_resource_resgroup-82 + Resources + + + + l_computeResource_domain-c101 + AVAYA1 + + l_host_host-16775 + itdbisvm-av04.nd.gov + + + l_host_host-16595 + itdbisvm-av02.nd.gov + + + l_host_host-16583 + itdbisvm-av01.nd.gov + + + l_host_host-16771 + itdbisvm-av03.nd.gov + + + l_host_host-16408 + itdbisvm-av05.nd.gov + + + l_resource_resgroup-102 + Resources + + + + l_computeResource_domain-c103 + LINUX1 + + l_host_host-2000 + itdbisvm-lin02.nd.gov + + + l_host_host-3834 + itdbisvm-gen03.nd.gov + + + l_host_host-1904 + itdbisvm-gen02.nd.gov + + + l_host_host-41441 + itdbisvm-gen01.nd.gov + + + l_host_host-1962 + itdbisvm-lin01.nd.gov + + + l_host_host-2092 + itdbisvm-gen04.nd.gov + + + l_host_host-2197 + itdbisvm-lin03.nd.gov + + + l_resource_resgroup-104 + Resources + + + + l_computeResource_domain-c107 + ORACLE1 + + l_host_host-1309 + itdappvm171.nd.gov + + + l_host_host-1294 + itdappvm170.nd.gov + + + l_host_host-1326 + itdbisvm-ora01.nd.gov + + + l_resource_resgroup-108 + Resources + + + + l_computeResource_domain-c109 + PS1 + + l_host_host-1097 + itdbisvm-ps06.nd.gov + + + l_host_host-1196 + itdbisvm-ps09.nd.gov + + + l_host_host-1063 + itdbisvm-ps05.nd.gov + + + l_host_host-1037 + itdbisvm-ps03.nd.gov + + + l_host_host-1133 + itdbisvm-ps07.nd.gov + + + l_host_host-1014 + itdbisvm-ps02.nd.gov + + + l_host_host-875 + itdbisvm-ps01.nd.gov + + + l_host_host-1165 + itdbisvm-ps08.nd.gov + + + l_host_host-989 + itdbisvm-ps04.nd.gov + + + l_resource_resgroup-110 + Resources + + + + l_folder_group-h46544 + DOCR + + l_computeResource_domain-s46545 + itdbisvm-docr1.nd.gov + + l_host_host-46547 + itdbisvm-docr1.nd.gov + + + l_resource_resgroup-46546 + Resources + + + + + + l_network_network-46550 + PG_2294_10.2.33.0_24 + + + l_network_network-44427 + VM Network + + + l_network_dvportgroup-426 + dvPG_4044_10.2.100.176_28 + + + l_network_dvportgroup-427 + dvPG_4045_10.2.100.192_28 + + + l_network_dvportgroup-46553 + dvPG_1839_10.2.114.128_28 + + + l_network_dvportgroup-409 + dvPG_3944_10.2.81.144_28 + + + l_network_dvportgroup-660 + dvPG_1720_10.2.108.16_28 + + + l_network_dvportgroup-398 + dvPG_1832_10.2.114.48_28 + + + l_network_dvportgroup-401 + dvPG_1767_10.2.111.16_28 + + + l_network_dvportgroup-397 + dvPG_4013_10.2.81.160_28 + + + l_network_dvportgroup-315 + dvPG_1724_10.2.108.80_28 + + + l_network_dvportgroup-390 + dvPG_4055_10.2.101.112_28 + + + l_network_dvportgroup-394 + dvPG_4053_10.2.101.80_28 + + + l_network_dvportgroup-386 + dvPG_1879_10.221.8.208_28 + + + l_network_dvportgroup-377 + dvPG_1874_10.221.11.64_27 + + + l_network_dvportgroup-25880 + dvPG_1915_10.221.10.240_28 + + + l_network_dvportgroup-366 + dvPG_1813_10.2.113.80_28 + + + l_network_dvportgroup-647 + dvPG_0174_165.234.112.0_29 + + + l_network_dvportgroup-361 + dvPG_1876_10.221.8.160_28 + + + l_network_dvportgroup-364 + dvPG_4042_10.2.100.144_28 + + + l_network_dvportgroup-41232 + dvPG_3834_10.2.95.96_28 + + + l_network_dvportgroup-535 + dvPG_3726_10.2.82.80_28 + + + l_network_dvportgroup-389 + dvPG_1884_10.221.9.32_28 + + + l_network_dvportgroup-23205 + dvPG_3971_10.2.152.0_27 + + + l_network_dvportgroup-40504 + dvPG_3708_10.2.93.112_28 + + + l_network_dvportgroup-39562 + dvPG_3816_10.2.93.0_28 + + + l_network_dvportgroup-540 + dvPG_3805_10.2.92.80_28 + + + l_network_dvportgroup-38619 + dvPG_3996_10.2.164.32_28 + + + l_network_dvportgroup-675 + dvPG_0036_10.2.29.0_24 + + + l_network_dvportgroup-440 + dvPG_1801_10.2.112.160_28 + + + l_network_dvportgroup-38618 + dvPG_3997_10.2.164.48_28 + + + l_network_dvportgroup-325 + dvPG_1723_10.2.108.64_28 + + + l_network_dvportgroup-40502 + dvPG_3684_10.2.93.128_28 + + + l_network_dvportgroup-39564 + dvPG_3818_10.2.93.32_28 + + + l_network_dvportgroup-38431 + dvPG_3596_10.2.163.208_28 + + + l_network_dvportgroup-38429 + dvPG_3594_10.2.163.176_28 + + + l_network_dvportgroup-25844 + dvPG_1858_10.221.7.192_28 + + + l_network_dvportgroup-41231 + dvPG_3830_10.2.22.0_26 + + + l_network_dvportgroup-490 + dvPG_3844_10.2.85.144_28 + + + l_network_dvportgroup-324 + dvPG_4077_10.2.101.240_28 + + + l_network_dvportgroup-37200 + dvPG_3357_10.8.137.128_29 + + + l_network_dvportgroup-392 + dvPG_4054_10.2.101.96_28 + + + l_network_dvportgroup-25858 + dvPG_1881_10.221.8.240_28 + + + l_network_dvportgroup-27876 + dvPG_3320_10.2.151.176_28 + + + l_network_dvportgroup-26554 + dvPG_3500_10.2.123.80_28 + + + l_network_dvportgroup-25866 + dvPG_1894_10.221.9.192_28 + + + l_network_dvportgroup-25868 + dvPG_1896_10.221.9.224_28 + + + l_network_dvportgroup-388 + dvPG_4056_10.2.101.128_28 + + + l_network_dvportgroup-688 + dvPG_3932_10.2.97.80_28 + + + l_network_dvportgroup-27878 + dvPG_3322_10.2.160.192_28 + + + l_network_dvportgroup-25873 + dvPG_1907_10.221.10.112_28 + + + l_network_dvportgroup-276 + dvPG_3763_10.2.86.160_28 + + + l_network_dvportgroup-38425 + dvPG_3598_10.2.163.240_28 + + + l_network_dvportgroup-624 + dvPG_3858_10.2.97.32_28 + + + l_network_dvportgroup-268 + dvPG_1742_10.2.109.48_28 + + + l_network_dvportgroup-37202 + dvPG_3348_10.2.163.48_28 + + + l_network_dvportgroup-25878 + dvPG_1912_10.221.10.192_28 + + + l_network_dvportgroup-30643 + dvPG_3334_10.2.161.192_28 + + + l_network_dvportgroup-722 + dvPG_1808_10.2.112.224_28 + + + l_network_dvportgroup-354 + dvPG_1711_10.2.107.128_28 + + + l_network_dvportgroup-11071 + dvPG_1969_10.2.119.160_28 + + + l_network_dvportgroup-211 + dvPG_3756_10.2.86.80_28 + + + l_network_dvportgroup-314 + dvPG_1710_10.2.14.0_28 + + + l_network_dvportgroup-27931 + dvPG_1983_10.2.160.144_28 + + + l_network_dvportgroup-25840 + dvPG_1854_10.221.7.128_28 + + + l_network_dvportgroup-378 + dvPG_1875_10.221.11.96_27 + + + l_network_dvportgroup-310 + dvPG_1743_10.2.109.192_28 + + + l_network_dvportgroup-351 + dvPG_1703_10.2.107.32_28 + + + l_network_dvportgroup-30641 + dvPG_3318_10.2.161.176_28 + + + l_network_dvportgroup-574 + dvPG_1754_10.2.110.64_28 + + + l_network_dvportgroup-720 + dvPG_1807_10.2.112.208_28 + + + l_network_dvportgroup-414 + dvPG_1819_10.2.113.176_28 + + + l_network_dvportgroup-28598 + dvPG_3961_10.2.123.160_28 + + + l_network_dvportgroup-486 + dvPG_1145_10.2.6.0_24 + + + l_network_dvportgroup-29141 + dvPG_3327_10.2.161.0_28 + + + l_network_dvportgroup-45232 + dvPG_1105_10.2.166.80_28 + + + l_network_dvportgroup-27544 + dvPG_0726_10.8.154.192_29 + + + l_network_dvportgroup-240 + dvPG_3688_10.2.80.48_28 + + + l_network_dvportgroup-26894 + dvPG_1845_10.2.114.192_28 + + + l_network_dvportgroup-767 + dvPG_PDC_AVAYA_VMOTION + + + l_network_dvportgroup-719 + dvPG_0259_10.2.39.0_24 + + + l_network_dvportgroup-294 + dvPG_1901_10.221.10.0_26 + + + l_network_dvportgroup-27932 + dvPG_3669_10.2.160.128_28 + + + l_network_dvportgroup-448 + dvPG_4025_10.2.99.192_28 + + + l_network_dvportgroup-235 + dvPG_4040_10.2.100.112_28 + + + l_network_dvportgroup-50595 + dvPG_702_10.2.103.128_28 + + + l_network_dvportgroup-25864 + dvPG_1892_10.221.9.160_27 + + + l_network_dvportgroup-17140 + dvPG_3430_10.2.122.32_28 + + + l_network_dvportgroup-305 + dvPG_3754_10.2.98.80_28 + + + l_network_dvportgroup-306 + dvPG_0133_10.2.135.248_29 + + + l_network_dvportgroup-376 + dvPG_1873_10.221.11.32_27 + + + l_network_dvportgroup-29687 + dvPG_3329_10.2.161.80_28 + + + l_network_dvportgroup-19074 + dvPG_3435_10.2.122.112_28 + + + l_network_dvportgroup-25863 + dvPG_1889_10.221.9.112_28 + + + l_network_dvportgroup-39563 + dvPG_3817_10.2.93.16_28 + + + l_network_dvportgroup-511 + dvPG_2476_10.8.71.0_28 + + + l_network_dvportgroup-25856 + dvPG_1871_10.221.8.144_28 + + + l_network_dvportgroup-301 + dvPG_3823_10.2.95.16_28 + + + l_network_dvportgroup-30642 + dvPG_3317_10.2.161.144_28 + + + l_network_dvportgroup-29143 + dvPG_0140_10.2.152.144_28 + + + l_network_dvportgroup-254 + dvPG_3695_10.2.80.160_28 + + + l_network_dvportgroup-573 + dvPG_1755_10.2.110.80_28 + + + l_network_dvportgroup-25849 + dvPG_1863_10.221.8.16_28 + + + l_network_dvportgroup-15281 + dvPG_1999_10.2.120.208_28 + + + l_network_dvportgroup-41233 + dvPG_3950_165.234.142.0_24 + + + l_network_dvportgroup-38426 + dvPG_3591_10.2.163.128_28 + + + l_network_dvportgroup-29360 + dvPG_3513_10.2.161.64_28 + + + l_network_dvportgroup-705 + dvPG_3712_10.2.81.16_28 + + + l_network_dvportgroup-496 + dvPG_3725_10.2.82.64_28 + + + l_network_dvportgroup-25854 + dvPG_1868_10.221.8.96_28 + + + l_network_dvportgroup-437 + dvPG_1824_10.2.113.224_28 + + + l_network_dvportgroup-25861 + dvPG_1886_10.221.9.64_28 + + + l_network_dvportgroup-25852 + dvPG_1866_10.221.8.64_28 + + + l_network_dvportgroup-25846 + dvPG_1860_10.221.7.224_28 + + + l_network_dvportgroup-274 + dvPG_3691_10.2.80.96_28 + + + l_network_dvportgroup-25875 + dvPG_1909_10.221.10.144_28 + + + l_network_dvportgroup-280 + dvPG_3690_10.2.80.80_28 + + + l_network_dvportgroup-353 + dvPG_1701_10.2.107.0_28 + + + l_network_dvportgroup-279 + dvPG_3689_10.2.80.64_28 + + + l_network_dvportgroup-230 + dvPG_3826_10.2.84.240_28 + + + l_network_dvportgroup-27875 + dvPG_3963_10.2.160.176_28 + + + l_network_dvportgroup-764 + dvPG_PDC_AVAYA_MGMT + + + l_network_dvportgroup-5961 + dvPG_1951_10.2.118.160_28 + + + l_network_dvportgroup-328 + dvPG_0087_10.2.81.240_28 + + + l_network_dvportgroup-8822 + dvPG_1960_10.2.118.144_28 + + + l_network_dvportgroup-12261 + dvPG_1955_10.2.120.64_28 + + + l_network_dvportgroup-25099 + dvPG_169_10.2.160.16_28 + + + l_network_dvportgroup-730 + dvPG_3884_10.2.98.32_28 + + + l_network_dvportgroup-25050 + dvPG_0180_10.2.160.64_28 + + + l_network_dvportgroup-517 + dvPG-ITDINTLB-INT-TRNK + + + l_network_dvportgroup-650 + dvPG_1399_165.234.125.0_24 + + + l_network_dvportgroup-467 + dvPG_3852_10.2.95.176_28 + + + l_network_dvportgroup-713 + dvPG_3882_10.2.98.0_28 + + + l_network_dvportgroup-48677 + dvPG_2280_10.2.152.160_28 + + + l_network_dvportgroup-23207 + dvPG_3973_10.2.152.64_27 + + + l_network_dvportgroup-4372 + dvPG_1933_10.2.115.160_28 + + + l_network_dvportgroup-40505 + dvPG_2000_10.2.166.0_28 + + + l_network_dvportgroup-242 + dvPG_1906_10.221.10.96_28 + + + l_network_dvportgroup-25869 + dvPG_1897_10.221.9.240_28 + + + l_network_dvportgroup-581 + dvPG_3737_10.2.84.0_28 + + + l_network_dvportgroup-25929 + dvPG_3449_10.2.151.160_28 + + + l_network_dvportgroup-420 + dvPG_1783_10.2.111.192_28 + + + l_network_dvportgroup-40211 + dvPG_3713_10.2.165.0_28 + + + l_network_dvportgroup-28597 + dvPG_3960_10.2.123.144_28 + + + l_network_dvportgroup-628 + dvPG_3699_10.2.13.16_28 + + + l_network_dvportgroup-616 + dvPG_3545_10.30.0.0_20 + + + l_network_dvportgroup-37201 + dvPG_3359_10.8.137.144_29 + + + l_network_dvportgroup-29305 + dvPG_3511_10.2.161.32_28 + + + l_network_dvportgroup-9633 + dvPG_1965_10.2.119.48_28 + + + l_network_dvportgroup-233 + dvPG_2351_10.8.34.208_28 + + + l_network_dvportgroup-40506 + dvPG_2001_10.2.166.16_28 + + + l_network_dvportgroup-23209 + dvPG_3974_10.2.152.96_27 + + + l_network_dvportgroup-226 + dvPG_3723_10.2.82.32_28 + + + l_network_dvportgroup-25862 + dvPG_1887_10.221.9.80_28 + + + l_network_dvportgroup-441 + dvPG_1802_10.2.112.176_28 + + + l_network_dvportgroup-15836 + dvPG_3414_10.2.121.0_28 + + + l_network_dvportgroup-473 + dvPG_3854_10.2.95.208_28 + + + l_network_dvportgroup-29071 + dvPG_0155_10.2.152.128_28 + + + l_network_dvportgroup-277 + dvPG_3692_10.2.80.112_28 + + + l_network_dvportgroup-229 + dvPG_2393_10.2.32.0_24 + + + l_network_dvportgroup-14364 + dvPG_0608_10.2.120.176_28 + + + l_network_dvportgroup-645 + dvPG_3800_10.2.92.0_28 + + + l_network_dvportgroup-29306 + dvPG_3512_10.2.161.48_28 + + + l_network_dvportgroup-26893 + dvPG_3426_10.2.122.0_28 + + + l_network_dvportgroup-507 + dvPG_3940_10.2.97.240_28 + + + l_network_dvportgroup-23155 + dvPG_3983_10.2.151.80_28 + + + l_network_dvportgroup-655 + dvPG_0175_10.2.140.0_28 + + + l_network_dvportgroup-611 + dvPG_0163_10.2.34.0_24 + + + l_network_dvportgroup-543 + dvPG_3770_10.2.81.224_28 + + + l_network_dvportgroup-25839 + dvPG_1853_10.221.7.112_28 + + + l_network_dvportgroup-731 + dvPG_3883_10.2.98.16_28 + + + l_network_dvportgroup-38432 + dvPG_3597_10.2.163.224_28 + + + l_network_dvportgroup-304 + dvPG_4008_10.2.140.192_28 + + + l_network_dvportgroup-775 + dvPG_0543_165.234.136.0_24_TEL + + + l_network_dvportgroup-37206 + dvPG_3362_10.8.137.168_29 + + + l_network_dvportgroup-11072 + dvPG_1986_10.2.119.176_28 + + + l_network_dvportgroup-217 + dvPG_1740_10.2.109.160_28 + + + l_network_dvportgroup-45733 + dvPG_202_10.2.0.0_28 + + + l_network_dvportgroup-648 + dvPG_0743_10.8.139.32_27 + + + l_network_dvportgroup-37041 + dvPG_1840_10.2.162.160_28 + + + l_network_dvportgroup-38093 + dvPG_3451_10.2.163.112_28 + + + l_network_dvportgroup-558 + dvPG_3803_10.2.92.48_28 + + + l_network_dvportgroup-25843 + dvPG_1857_10.221.7.176_28 + + + l_network_dvportgroup-430 + dvPG_1805_10.2.113.0_28 + + + l_network_dvportgroup-432 + dvPG_1823_10.2.113.208_28 + + + l_network_dvportgroup-418 + dvPG_1745_10.2.109.224_28 + + + l_network_dvportgroup-506 + dvPG_3936_10.2.97.208_28 + + + l_network_dvportgroup-8825 + dvPG_1963_10.2.119.16_28 + + + l_network_dvportgroup-476 + dvPG_4052_10.2.101.64_28 + + + l_network_dvportgroup-41230 + dvPG_2430_10.2.20.0_24_AVAYA + + + l_network_dvportgroup-358 + dvPG_1865_10.221.8.48_28 + + + l_network_dvportgroup-729 + dvPG_0045_10.2.8.0_24_Custom + + + l_network_dvportgroup-531 + dvPG_3703_10.8.34.224_28 + + + l_network_dvportgroup-501 + dvPG_2451_165.234.44.16_28 + + + l_network_dvportgroup-436 + dvPG_1825_10.2.113.240_28 + + + l_network_dvportgroup-41525 + dvPG_2002_10.2.166.32_28 + + + l_network_dvportgroup-466 + dvPG_1774_10.2.111.112_28 + + + l_network_dvportgroup-664 + dvPG_4078_10.2.106.64_28 + + + l_network_dvportgroup-456 + dvPG_4051_10.2.101.48_28 + + + l_network_dvportgroup-612 + dvPG_3716_10.2.81.80_28 + + + l_network_dvportgroup-472 + dvPG_1826_10.2.114.0_28 + + + l_network_dvportgroup-49219 + dvPG_1924_10.2.165.80_28 + + + l_network_dvportgroup-15840 + dvPG_3418_10.2.121.64_28 + + + l_network_dvportgroup-25867 + dvPG_1895_10.221.9.208_28 + + + l_network_dvportgroup-225 + dvPG_3663_10.2.12.208_28 + + + l_network_dvportgroup-49806 + dvPG_2005_10.2.165.96_28 + + + l_network_dvportgroup-50594 + dvPG_701_10.2.103.112_28 + + + l_network_dvportgroup-265 + dvPG_4084_10.2.106.128_28 + + + l_network_dvportgroup-455 + dvPG_3856_10.2.97.0_28 + + + l_network_dvportgroup-312 + dvPG_1709_10.2.14.16_28 + + + l_network_dvportgroup-470 + dvPG_1796_10.2.112.80_28 + + + l_network_dvportgroup-715 + dvPG_0262_10.2.36.0_24 + + + l_network_dvportgroup-483 + dvPG_2322_10.8.139.192_27 + + + l_network_dvportgroup-15842 + dvPG_3420_10.2.121.96_28 + + + l_network_dvportgroup-497 + dvPG_0116_10.221.3.0_24 + + + l_network_dvportgroup-504 + dvPG_3778_10.2.84.112_28 + + + l_network_dvportgroup-498 + dvPG_3839_10.2.85.128_28 + + + l_network_dvportgroup-275 + dvPG_0744_10.8.139.64_27 + + + l_network_dvportgroup-37042 + dvPG_1841_10.2.162.208_28 + + + l_network_dvportgroup-565 + dvPG_3739_10.2.84.16_28 + + + l_network_dvportgroup-513 + dvPG_2341_10.2.64.0_24 + + + l_network_dvportgroup-510 + dvPG_2396_165.234.44.8_29 + + + l_network_dvportgroup-25877 + dvPG_1911_10.221.10.176_28 + + + l_network_dvportgroup-38427 + dvPG_3592_10.2.163.144_28 + + + l_network_dvportgroup-596 + dvPG_3824_10.2.95.32_28 + + + l_network_dvportgroup-589 + dvPG_3814_10.2.92.224_28 + + + l_network_dvportgroup-744 + dvPG_3674_10.8.154.224_28 + + + l_network_dvportgroup-661 + dvPG_1396_10.8.154.64_26 + + + l_network_dvportgroup-597 + dvPG_4046_10.2.100.208_28 + + + l_network_dvportgroup-465 + dvPG_1732_10.2.108.208_28 + + + l_network_dvportgroup-341 + dvPG_1708_10.2.12.144_28 + + + l_network_dvportgroup-685 + dvPG_3634_10.2.135.0_30 + + + l_network_dvportgroup-638 + dvPG_1736_10.2.109.16_28 + + + l_network_dvportgroup-419 + dvPG_1781_10.2.111.160_28 + + + l_network_dvportgroup-528 + dvPG_2468_10.34.154.16_28 + + + l_network_dvportgroup-374 + dvPG_4065_10.2.101.176_28 + + + l_network_dvportgroup-317 + dvPG_1726_10.2.108.112_28 + + + l_network_dvportgroup-572 + dvPG_1756_10.2.110.96_28 + + + l_network_dvportgroup-45381 + dvPG_1186_10.2.72.0_23 + + + l_network_dvportgroup-679 + dvPG_PDC_MGMT_VM + + + l_network_dvportgroup-450 + dvPG_1800_10.2.112.144_28 + + + l_network_dvportgroup-41005 + dvPG_2003_10.2.166.48_28 + + + l_network_dvportgroup-23153 + dvPG_3981_10.2.151.48_28 + + + l_network_dvportgroup-702 + dvPG_3666_165.234.44.48_28 + + + l_network_dvportgroup-38350 + dvPG_4029_10.2.164.0_28 + + + l_network_dvportgroup-541 + dvPG_3766_10.2.86.176_28 + + + l_network_dvportgroup-48860 + dvPG_1921_10.2.166.96_28 + + + l_network_dvportgroup-291 + dvPG_1769_10.2.111.32_28 + + + l_network_dvportgroup-577 + dvPG_3809_10.2.92.144_28 + + + l_network_dvportgroup-568 + dvPG-IDS + + + l_network_dvportgroup-25160 + dvPG_3421_10.2.121.112_28 + + + l_network_dvportgroup-18774 + dvPG_3433_10.2.122.80_28 + + + l_network_dvportgroup-15839 + dvPG_3417_10.2.121.48_28 + + + l_network_dvportgroup-710 + dvPG_3554_165.234.121.0_25 + + + l_network_dvportgroup-629 + dvPG_1837_10.2.114.96_28 + + + l_network_dvportgroup-707 + dvPG_3704_10.8.34.240_28 + + + l_network_dvportgroup-750 + dvPG_PDC_VMOTION + + + l_network_dvportgroup-25051 + dvPG_0181_10.2.160.80_28 + + + l_network_dvportgroup-25874 + dvPG_1908_10.221.10.128_28 + + + l_network_dvportgroup-287 + dvPG_4090_10.8.137.64_28 + + + l_network_dvportgroup-31776 + dvPG_3509_10.2.161.240_28 + + + l_network_dvportgroup-521 + dvPG-ITDINTLB-EXT-TRNK + + + l_network_dvportgroup-307 + dvPG_3855_10.2.95.240_28 + + + l_network_dvportgroup-683 + dvPG_1780_10.2.149.32_27 + + + l_network_dvportgroup-243 + dvPG_0543_165.234.136.0_24_Data + + + l_network_dvportgroup-14363 + dvPG_0607_10.2.120.160_28 + + + l_network_dvportgroup-421 + dvPG_1782_10.2.111.176_28 + + + l_network_dvportgroup-311 + dvPG_1744_10.2.109.208_28 + + + l_network_dvportgroup-734 + dvPG_1777_10.2.138.64_26 + + + l_network_dvportgroup-33547 + dvPG_2222_1.2.3.4_11 + + + l_network_dvportgroup-701 + dvPG_3658_10.2.12.128_28 + + + l_network_dvportgroup-626 + dvPG_1343_10.2.55.0_24 + + + l_network_dvportgroup-451 + dvPG_4023_10.2.99.160_28 + + + l_network_dvportgroup-772 + dvPG_0106_10.35.251.0_24 + + + l_network_dvportgroup-33875 + dvPG_3351_10.2.162.112_28 + + + l_network_dvportgroup-668 + dvPG_4003_10.2.98.176_28 + + + l_network_dvportgroup-562 + dvPG_3730_10.2.82.144_28 + + + l_network_dvportgroup-454 + dvPG_4066_10.2.106.0_28 + + + l_network_dvportgroup-257 + dvPG_1914_10.221.10.224_28 + + + l_network_dvportgroup-590 + dvPG_2404_10.2.133.192_26 + + + l_network_dvportgroup-520 + dvPG_2478_10.8.71.32_28 + + + l_network_dvportgroup-42818 + dvPG_3001_10.2.115.240_28 + + + l_network_dvportgroup-42819 + dvPG_3000_10.2.123.224_28 + + + l_network_dvportgroup-457 + dvPG_3857_10.2.97.16_28 + + + l_network_dvportgroup-41690 + dvPG_3683_10.2.93.144_28 + + + l_network_dvportgroup-5964 + dvPG_1954_10.2.118.208_28 + + + l_network_dvportgroup-623 + dvPG_3709_10.2.80.224_28 + + + l_network_dvportgroup-33874 + dvPG_3350_10.2.162.96_28 + + + l_network_dvportgroup-625 + dvPG_3700_10.2.13.32_28 + + + l_network_dvportgroup-503 + dvPG_3842_10.2.96.0_25 + + + l_network_dvportgroup-680 + dvPG_3751_10.2.86.64_28 + + + l_network_dvportgroup-458 + dvPG_3837_10.8.137.32_27 + + + l_network_dvportgroup-399 + dvPG_1731_10.2.108.192_28 + + + l_network_dvportgroup-637 + dvPG_1761_10.2.110.176_28 + + + l_network_dvportgroup-551 + dvPG_4087_10.2.103.16_29 + + + l_network_dvportgroup-396 + dvPG_4014_10.2.81.176_28 + + + l_network_dvportgroup-244 + dvPG_1905_10.221.10.80_28 + + + l_network_dvportgroup-620 + dvPG_3717_10.2.81.96_28 + + + l_network_dvportgroup-272 + dvPG_1831_10.2.114.32_28 + + + l_network_dvportgroup-493 + dvPG_2449_10.2.140.64_28 + + + l_network_dvportgroup-591 + dvPG_2405_10.2.134.0_26 + + + l_network_dvportgroup-263 + dvPG_3693_10.2.80.128_28 + + + l_network_dvportgroup-368 + dvPG_1869_10.221.8.112_28 + + + l_network_dvportgroup-547 + dvPG_3806_10.2.92.96_28 + + + l_network_dvportgroup-38428 + dvPG_3593_10.2.163.160_28 + + + l_network_dvportgroup-15365 + dvPG_4071_10.2.120.224_28 + + + l_network_dvportgroup-474 + dvPG_3853_10.2.95.192_28 + + + l_network_dvportgroup-735 + dvPG_3650_10.2.12.0_28 + + + l_network_dvportgroup-559 + dvPG_1760_10.2.110.160_28 + + + l_network_dvportgroup-292 + dvPG_1766_10.2.110.240_28 + + + l_network_dvportgroup-29018 + dvPG_3325_10.2.160.224_28 + + + l_network_dvportgroup-689 + dvPG_2472_10.8.139.232_29 + + + l_network_dvportgroup-462 + dvPG_1733_10.2.108.224_28 + + + l_network_dvportgroup-29017 + dvPG_3324_10.2.151.240_28 + + + l_network_dvportgroup-42983 + dvPG_114_10.2.114.240_28 + + + l_network_dvportgroup-227 + dvPG_3664_10.2.12.224_28 + + + l_network_dvportgroup-380 + dvPG_4060_10.2.100.240_28 + + + l_network_dvportgroup-10007 + dvPG_1961_10.2.118.224_28 + + + l_network_dvportgroup-723 + dvPG_2408_10.2.134.192_26 + + + l_network_dvportgroup-11073 + dvPG_1987_10.2.119.192_28 + + + l_network_dvportgroup-36735 + dvPG_1062_10.2.160.160_28 + + + l_network_dvportgroup-289 + dvPG_1772_10.2.111.80_28 + + + l_network_dvportgroup-262 + dvPG_3694_10.2.80.144_28 + + + l_network_dvportgroup-41527 + dvPG_3866_10.2.123.208_28 + + + l_network_dvportgroup-8733 + dvPG_4075_10.2.101.208_28 + + + l_network_dvportgroup-331 + dvPG_4012_10.2.81.128_28 + + + l_network_dvportgroup-7697 + dvPG_0534_10.2.139.32_28 + + + l_network_dvportgroup-286 + dvPG_4017_10.2.99.64_28 + + + l_network_dvportgroup-583 + dvPG_3715_10.2.81.64_28 + + + l_network_dvportgroup-684 + dvPG_0737_165.234.153.192_26 + + + l_network_dvportgroup-342 + dvPG_3829_10.2.95.80_28 + + + l_network_dvportgroup-48861 + dvPG_1922_10.2.166.112_28 + + + l_network_dvportgroup-45382 + dvPG_1187_10.2.76.0_22 + + + l_network_dvportgroup-23151 + dvPG_3979_10.2.151.16_28 + + + l_network_dvportgroup-11696 + dvPG_1958_10.2.120.16_28 + + + l_network_dvportgroup-667 + dvPG_0100_10.221.5.0_24 + + + l_network_dvportgroup-634 + dvPG_3667_165.234.44.64_28 + + + l_network_dvportgroup-745 + dvPG_0200_10.2.16.0_23 + + + l_network_dvportgroup-484 + dvPG_3847_10.2.85.192_28 + + + l_network_dvportgroup-18072 + dvPG_3431_10.2.122.48_28 + + + l_network_dvportgroup-733 + dvPG_3885_10.2.98.48_28 + + + l_network_dvportgroup-25161 + dvPG_3422_10.2.121.128_28 + + + l_network_dvportgroup-49300 + dvPG_1923_10.2.165.64_28 + + + l_network_dvportgroup-349 + dvPG_1702_10.2.107.16_28 + + + l_network_dvportgroup-11490 + dvPG_1989_10.2.119.224_28 + + + l_network_dvportgroup-606 + dvPG_1752_10.2.110.32_28 + + + l_network_dvportgroup-25847 + dvPG_1861_10.221.7.240_28 + + + l_network_dvportgroup-15837 + dvPG_3415_10.2.121.16_28 + + + l_network_dvportgroup-37440 + dvPG_3413_10.2.163.80_28 + + + l_network_dvportgroup-438 + dvPG_1791_10.2.111.240_28 + + + l_network_dvportgroup-41526 + dvPG_3865_10.2.123.192_28 + + + l_network_dvportgroup-11074 + dvPG_1988_10.2.119.208_28 + + + l_network_dvportgroup-452 + dvPG_4068_10.2.106.32_28 + + + l_network_dvportgroup-646 + dvPG_3850_10.2.95.144_28 + + + l_network_dvportgroup-477 + dvPG_0176_10.2.140.16_28 + + + l_network_dvportgroup-36279 + dvPG_1097_10.221.11.192_26 + + + l_network_dvportgroup-494 + dvPG_3846_10.2.85.176_28 + + + l_network_dvportgroup-657 + dvPG_4080_10.2.106.96_28 + + + l_network_dvportgroup-215 + dvPG_3998_10.2.109.64_28 + + + l_network_dvportgroup-737 + dvPG_0007_10.2.9.0_24 + + + l_network_dvportgroup-700 + dvPG_2348_10.8.34.128_27 + + + l_network_dvportgroup-429 + dvPG_1792_10.2.112.48_28 + + + l_network_dvportgroup-313 + dvPG_1722_10.2.108.48_28 + + + l_network_dvportgroup-703 + dvPG_2347_10.8.34.96_27 + + + l_network_dvportgroup-423 + dvPG_1784_10.2.111.208_28 + + + l_network_dvportgroup-48923 + dvPG_3402_10.2.163.16_29 + + + l_network_dvportgroup-742 + dvPG_3651_10.2.12.16_28 + + + l_network_dvportgroup-553 + dvPG_3801_10.2.92.16_28 + + + l_network_dvportgroup-608 + dvPG_3736_10.2.88.0_24 + + + l_network_dvportgroup-717 + dvPG_3864_10.2.97.224_28 + + + l_network_dvportgroup-25853 + dvPG_1867_10.221.8.80_28 + + + l_network_dvportgroup-5790 + dvPG_1944_10.2.118.32_28 + + + l_network_dvportgroup-560 + dvPG_0097_10.2.138.0_26 + + + l_network_dvportgroup-599 + dvPG_4089_10.2.106.192_28 + + + l_network_dvportgroup-221 + dvPG_3906_10.2.98.208_28 + + + l_network_dvportgroup-492 + dvPG_3845_10.2.85.160_28 + + + l_network_dvportgroup-741 + dvPG_3652_10.2.12.32_28 + + + l_network_dvportgroup-594 + dvPG_3811_10.2.92.176_28 + + + l_network_dvportgroup-464 + dvPG_3836_10.8.137.0_27 + + + l_network_dvportgroup-48922 + dvPG_2004_10.2.163.8_29 + + + l_network_dvportgroup-725 + dvPG_2407_10.2.134.128_26 + + + l_network_dvportgroup-570 + dvPG_3740_10.2.85.0_25 + + + l_network_dvportgroup-41234 + dvPG_3951_165.234.37.0_28 + + + l_network_dvportgroup-538 + dvPG_3660_10.2.12.160_28 + + + l_network_dvportgroup-34045 + dvPG_3985_10.2.162.176_28 + + + l_network_dvportgroup-514 + dvPG_3772_10.2.84.32_28 + + + l_network_dvportgroup-21084 + dvPG_3443_10.2.122.224_28 + + + l_network_dvportgroup-491 + dvPG_0728_10.8.153.128_26 + + + l_network_dvportgroup-556 + dvPG_3861_10.2.95.224_28 + + + l_network_dvportgroup-487 + dvPG_1395_10.8.154.0_26 + + + l_network_dvportgroup-439 + dvPG_1803_10.2.112.192_28 + + + l_network_dvportgroup-604 + dvPG_1753_10.2.110.48_28 + + + l_network_dvportgroup-269 + dvPG_4085_10.2.106.144_28 + + + l_network_dvportgroup-428 + dvPG_1820_10.2.149.64_27 + + + l_network_dvportgroup-550 + dvPG_3802_10.2.92.32_28 + + + l_network_dvportgroup-526 + dvPG_2469_10.34.154.32_28 + + + l_network_dvportgroup-567 + dvPG_3733_10.2.82.192_28 + + + l_network_dvportgroup-48071 + dvPG_3401_10.2.165.16_28 + + + l_network_dvportgroup-449 + dvPG_4069_10.2.106.48_28 + + + l_network_dvportgroup-642 + dvPG_0736_10.8.153.192_26 + + + l_network_dvportgroup-533 + dvPG_3728_10.2.82.112_28 + + + l_network_dvportgroup-704 + dvPG_1786_10.2.112.16_28 + + + l_network_dvportgroup-656 + dvPG_4079_10.2.106.80_28 + + + l_network_dvportgroup-481 + dvPG_3710_10.2.80.240_28 + + + l_network_dvportgroup-480 + dvPG_3685_10.2.80.0_28 + + + l_network_dvportgroup-363 + dvPG_1878_10.221.8.192_28 + + + l_network_dvportgroup-25881 + dvPG_3590_10.2.151.144_28 + + + l_network_dvportgroup-716 + dvPG_3862_10.2.97.112_28 + + + l_network_dvportgroup-22438 + dvPG_3446_10.2.123.16_28 + + + l_network_dvportgroup-485 + dvPG_3662_10.2.12.192_28 + + + l_network_dvportgroup-530 + dvPG_3727_10.2.82.96_28 + + + l_network_dvportgroup-267 + dvPG_3939_10.57.66.224_27 + + + l_network_dvportgroup-695 + dvPG_3686_10.2.80.16_28 + + + l_network_dvportgroup-666 + dvPG_0709_165.234.156.0_22 + + + l_network_dvportgroup-30644 + dvPG_3335_10.2.161.224_28 + + + l_network_dvportgroup-728 + dvPG_2403_10.2.133.128_26 + + + l_network_dvportgroup-502 + dvPG_2394_10.2.66.0_24 + + + l_network_dvportgroup-618 + dvPG_0263_10.2.37.0_24 + + + l_network_dvportgroup-580 + dvPG_3714_10.2.81.48_28 + + + l_network_dvportgroup-290 + dvPG_0251_10.2.107.80_28 + + + l_network_dvportgroup-643 + dvPG_3851_10.2.95.160_28 + + + l_network_dvportgroup-613 + dvPG_2345_10.8.34.32_27 + + + l_network_dvportgroup-38900 + dvPG_3706_10.8.139.248_29 + + + l_network_dvportgroup-561 + dvPG_1758_10.2.110.128_28 + + + l_network_dvportgroup-644 + dvPG_4073_10.2.81.208_28 + + + l_network_dvportgroup-41229 + dvPG_2279_165.234.164.32_27 + + + l_network_dvportgroup-740 + dvPG_0045_10.2.8.0_24 + + + l_network_dvportgroup-738 + dvPG_3653_10.2.12.48_28 + + + l_network_dvportgroup-36739 + dvPG_3356_10.8.137.120_29 + + + l_network_dvportgroup-649 + dvPG_1161_10.11.12.0_23 + + + l_network_dvportgroup-601 + dvPG_4088_10.2.106.176_28 + + + l_network_dvportgroup-252 + dvPG_0117_10.221.4.0_24 + + + l_network_dvportgroup-478 + dvPG_0739_10.8.139.0_27 + + + l_network_dvportgroup-224 + dvPG_0002_10.2.2.0_23 + + + l_network_dvportgroup-26458 + dvPG_3521_10.2.123.96_28 + + + l_network_dvportgroup-566 + dvPG_2398_10.2.132.64_26 + + + l_network_dvportgroup-234 + dvPG_4074_10.2.97.64_28 + + + l_network_dvportgroup-706 + dvPG_3774_10.2.84.64_27 + + + l_network_dvportgroup-555 + dvPG_3804_10.2.92.64_28 + + + l_network_dvportgroup-687 + dvPG_2471_10.8.139.224_29 + + + l_network_dvportgroup-536 + dvPG_4026_10.2.99.208_28 + + + l_network_dvportgroup-463 + dvPG_4048_10.2.101.0_28 + + + l_network_dvportgroup-508 + dvPG_3779_10.2.84.128_28 + + + l_network_dvportgroup-434 + dvPG_1822_10.2.113.192_28 + + + l_network_dvportgroup-237 + dvPG_4011_10.2.99.0_28 + + + l_network_dvportgroup-678 + dvPG_0747_10.8.139.128_27 + + + l_network_dvportgroup-38897 + dvPG_3360_10.8.137.152_29 + + + l_network_dvportgroup-557 + dvPG_2402_10.2.133.64_26 + + + l_network_dvportgroup-347 + dvPG_1705_10.2.107.64_28 + + + l_network_dvportgroup-682 + dvPG_PDC_MGMT + + + l_network_dvportgroup-671 + dvPG_4004_10.2.98.192_28 + + + l_network_dvportgroup-236 + dvPG_4041_10.2.100.128_28 + + + l_network_dvportgroup-11986 + dvPG_1984_10.2.120.32_28 + + + l_network_dvportgroup-579 + dvPG_3810_10.2.92.160_28 + + + l_network_dvportgroup-578 + dvPG_3943_10.2.98.64_28 + + + l_network_dvportgroup-345 + dvPG_1704_10.2.107.48_28 + + + l_network_dvportgroup-360 + dvPG_4039_10.2.100.96_28 + + + l_network_dvportgroup-563 + dvPG_1759_10.2.110.144_28 + + + l_network_dvportgroup-25838 + dvPG_1852_10.221.7.96_28 + + + l_network_dvportgroup-281 + dvPG_1771_10.2.111.64_28 + + + l_network_dvportgroup-575 + dvPG_3807_10.2.92.112_28 + + + l_network_dvportgroup-25860 + dvPG_1885_10.221.9.48_28 + + + l_network_dvportgroup-395 + dvPG_1888_10.221.9.96_28 + + + l_network_dvportgroup-545 + dvPG_3771_10.34.77.24_29 + + + l_network_dvportgroup-372 + dvPG_4034_10.2.100.64_28 + + + l_network_dvportgroup-662 + dvPG_1721_10.2.108.32_28 + + + l_network_dvportgroup-288 + dvPG_4091_10.8.137.80_28 + + + l_network_dvportgroup-25851 + dvPG_1864_10.221.8.32_28 + + + l_network_dvportgroup-658 + dvPG_1397_10.8.154.248_29 + + + l_network_dvportgroup-500 + dvPG_3721_10.2.82.0_28 + + + l_network_dvportgroup-726 + dvPG_2406_10.2.134.64_26 + + + l_network_dvportgroup-15847 + dvPG_3425_10.2.121.176_28 + + + l_network_dvportgroup-369 + dvPG_4064_10.2.101.160_28 + + + l_network_dvportgroup-621 + dvPG_3828_10.2.95.64_28 + + + l_network_dvportgroup-522 + dvPG_3933_10.2.97.160_28 + + + l_network_dvportgroup-519 + dvPG_3934_10.2.97.176_28 + + + l_network_dvportgroup-659 + dvPG_4081_10.2.106.112_28 + + + l_network_dvportgroup-45734 + dvPG_203_10.2.0.16_28 + + + l_network_dvportgroup-532 + dvPG_2399_10.2.132.128_26 + + + l_network_dvportgroup-333 + dvPG_3790_10.2.84.160_28 + + + l_network_dvportgroup-539 + dvPG_1714_10.2.107.176_28 + + + l_network_dvportgroup-639 + dvPG_4072_10.2.81.192_28 + + + l_network_dvportgroup-516 + dvPG_2458_10.2.10.16_29 + + + l_network_dvportgroup-278 + dvPG_2389_10.8.154.240_29 + + + l_network_dvportgroup-25842 + dvPG_1856_10.221.7.160_28 + + + l_network_dvportgroup-453 + dvPG_4067_10.2.106.16_28 + + + l_network_dvportgroup-690 + dvPG_3931_10.2.97.96_28 + + + l_network_dvportgroup-727 + dvPG_1394_10.2.60.0_23 + + + l_network_dvportgroup-619 + dvPG_3859_10.2.97.48_28 + + + l_network_dvportgroup-9348 + dvPG_1964_10.2.119.32_28 + + + l_network_dvportgroup-615 + dvPG_2344_10.8.34.0_27 + + + l_network_dvportgroup-460 + dvPG_1734_10.2.108.240_28 + + + l_network_dvportgroup-25101 + dvPG_0171_10.2.160.48_28 + + + l_network_dvportgroup-271 + dvPG_4086_10.2.106.160_28 + + + l_network_dvportgroup-571 + dvPG_1757_10.2.110.112_28 + + + l_network_dvportgroup-35387 + dvPG_0102_10.2.163.0_29 + + + l_network_dvportgroup-1583 + dvPG_1849_10.2.115.16_28 + + + l_network_dvportgroup-31721 + dvPG_3507_10.2.162.0_28 + + + l_network_dvportgroup-36169 + dvPG_1351_10.2.163.32_28 + + + l_network_dvportgroup-669 + dvPG_1778_10.2.138.128_26 + + + l_network_dvportgroup-778 + dvPG_PDC_TEL_MGMT + + + l_network_dvportgroup-673 + dvPG_0194_10.59.60.0_24 + + + l_network_dvportgroup-537 + dvPG_4062_10.2.105.0_24 + + + l_network_dvportgroup-283 + dvPG_1770_10.2.111.48_28 + + + l_network_dvportgroup-25876 + dvPG_1910_10.221.10.160_28 + + + l_network_dvportgroup-39565 + dvPG_3819_10.2.93.48_28 + + + l_network_dvportgroup-443 + dvPG_1798_10.2.112.112_28 + + + l_network_dvportgroup-362 + dvPG_1877_10.221.8.176_28 + + + l_network_dvportgroup-461 + dvPG_4049_10.2.101.16_28 + + + l_network_dvportgroup-35053 + dvPG_2485_10.2.162.192_28 + + + l_network_dvportgroup-33930 + dvPG_3355_10.2.162.144_28 + + + l_network_dvportgroup-36740 + dvPG_3358_10.8.137.136_29 + + + l_network_dvportgroup-25848 + dvPG_1862_10.221.8.0_28 + + + l_network_dvportgroup-293 + dvPG_1750_10.2.110.0_28 + + + l_network_dvportgroup-45231 + dvPG_1104_10.2.166.64_28 + + + l_network_dvportgroup-36224 + dvPG_4006_10.2.140.160_28 + + + l_network_dvportgroup-45735 + dvPG_2180_165.234.16.0_28 + + + l_network_dvportgroup-48678 + dvPG_2281_10.2.152.176_28 + + + l_network_dvportgroup-617 + dvPG_0258_10.2.42.0_24 + + + l_network_dvportgroup-19962 + dvPG_3440_10.2.122.176_28 + + + l_network_dvportgroup-34446 + dvPG_3890_10.2.162.48_28 + + + l_network_dvportgroup-36737 + dvPG_1064_10.2.161.160_28 + + + l_network_dvportgroup-36736 + dvPG_1063_10.2.160.208_28 + + + l_network_dvportgroup-663 + dvPG_1707_10.2.107.112_28 + + + l_network_dvportgroup-318 + dvPG_1727_10.2.108.128_28 + + + l_network_dvportgroup-29142 + dvPG_3328_10.2.161.16_28 + + + l_network_dvportgroup-747 + dvPG_1776_10.2.111.144_28 + + + l_network_dvportgroup-5962 + dvPG_1952_10.2.118.176_28 + + + l_network_dvportgroup-375 + dvPG_4033_10.2.100.48_28 + + + l_network_dvportgroup-25841 + dvPG_1855_10.221.7.144_28 + + + l_network_dvportgroup-14569 + dvPG_1926_10.2.115.32_28 + + + l_network_dvportgroup-30063 + dvPG_3330_10.2.161.96_28 + + + l_network_dvportgroup-674 + dvPG_4001_10.2.98.144_28 + + + l_network_dvportgroup-724 + dvPG_3860_10.2.86.208_28 + + + l_network_dvportgroup-33548 + dvPG_3889_10.2.162.32_28 + + + l_network_dvportgroup-593 + dvPG_3812_10.2.92.192_28 + + + l_network_dvportgroup-29019 + dvPG_3326_10.2.160.240_28 + + + l_network_dvportgroup-39566 + dvPG_3820_10.2.93.64_28 + + + l_network_dvportgroup-739 + dvPG_0076_10.221.6.0_24 + + + l_network_dvportgroup-781 + dvPG_PDC_TEL_VMOTION + + + l_network_dvportgroup-692 + dvPG_3697_10.2.80.192_28 + + + l_network_dvportgroup-50781 + dvPG_0703_10.2.166.128_28 + + + l_network_dvportgroup-379 + dvPG_1829_10.8.137.96_29 + + + l_network_dvportgroup-25859 + dvPG_1883_10.221.9.16_28 + + + l_network_dvportgroup-515 + dvPG_2459_10.34.154.0_28 + + + l_network_dvportgroup-22437 + dvPG_3445_10.2.123.0_28 + + + l_network_dvportgroup-554 + dvPG_3698_10.2.13.0_28 + + + l_network_dvportgroup-373 + dvPG_1872_10.221.11.0_27 + + + l_network_dvportgroup-709 + dvPG_2467_10.8.154.128_26 + + + l_network_dvportgroup-33876 + dvPG_3336_10.2.162.128_28 + + + l_network_dvportgroup-260 + dvPG_3761_10.2.86.144_28 + + + l_network_dvportgroup-316 + dvPG_1725_10.2.108.96_28 + + + l_network_dvportgroup-21085 + dvPG_3444_10.2.122.240_28 + + + l_network_dvportgroup-447 + dvPG_4092_10.2.103.24_29 + + + l_network_dvportgroup-27877 + dvPG_3321_10.2.151.192_28 + + + l_network_dvportgroup-25163 + dvPG_3424_10.2.121.160_28 + + + l_network_dvportgroup-459 + dvPG_4050_10.2.101.32_28 + + + l_network_dvportgroup-246 + dvPG_1904_10.221.11.160_27 + + + l_network_dvportgroup-303 + dvPG_4007_10.2.140.176_28 + + + l_network_dvportgroup-546 + dvPG_1717_10.2.107.224_28 + + + l_network_dvportgroup-8734 + dvPG_4076_10.2.101.224_28 + + + l_network_dvportgroup-335 + dvPG_1751_10.2.110.16_28 + + + l_network_dvportgroup-445 + dvPG_1797_10.2.112.96_28 + + + l_network_dvportgroup-712 + dvPG_0746_10.8.139.96_27 + + + l_network_dvportgroup-986 + dvPG_1847_10.2.114.224_28 + + + l_network_dvportgroup-512 + dvPG_2477_10.8.71.16_28 + + + l_network_dvportgroup-609 + dvPG_0742_10.8.153.64_26 + + + l_network_dvportgroup-26895 + dvPG_3427_10.2.122.16_28 + + + l_network_dvportgroup-4541 + dvPG_1934_10.2.115.176_28 + + + l_network_dvportgroup-25162 + dvPG_3423_10.2.121.144_28 + + + l_network_dvportgroup-26889 + dvPG_3589_10.2.151.128_28 + + + l_network_dvportgroup-25837 + dvPG_1851_10.221.7.80_28 + + + l_network_dvportgroup-12646 + dvPG_1842_10.2.114.144_28 + + + l_network_dvportgroup-381 + dvPG_4043_10.2.100.160_28 + + + l_network_dvportgroup-21082 + dvPG_3441_10.2.122.192_28 + + + l_network_dvportgroup-15841 + dvPG_3419_10.2.121.80_28 + + + l_network_dvportgroup-23206 + dvPG_3972_10.2.152.32_27 + + + l_network_dvportgroup-15838 + dvPG_3416_10.2.121.32_28 + + + l_network_dvportgroup-8823 + dvPG_1959_10.2.118.128_28 + + + l_network_dvportgroup-4414 + dvPG_1931_10.2.115.128_28 + + + l_network_dvportgroup-12647 + dvPG_1843_10.2.114.160_28 + + + l_network_dvportgroup-635 + dvPG_1712_10.2.107.144_28 + + + l_network_dvportgroup-38092 + dvPG_3450_10.2.163.96_28 + + + l_network_dvportgroup-1734 + dvPG_1927_10.2.115.48_28 + + + l_network_dvportgroup-691 + dvPG_3701_10.2.87.0_24 + + + l_network_dvportgroup-6521 + dvPG_1948_10.2.118.96_28 + + + l_network_dvportgroup-26459 + dvPG_0191_10.2.123.112_28 + + + l_network_dvportgroup-5963 + dvPG_1953_10.2.118.192_28 + + + l_network_dvportgroup-584 + dvPG_3711_10.2.81.0_28 + + + l_network_dvportgroup-442 + dvPG_1804_10.2.84.192_28 + + + l_network_dvportgroup-228 + dvPG_3722_10.2.82.16_28 + + + l_network_dvportgroup-37439 + dvPG_3412_10.2.163.64_28 + + + l_network_dvportgroup-238 + dvPG_1821_10.2.109.240_28 + + + l_network_dvportgroup-385 + dvPG_1882_10.221.9.0_28 + + + l_network_dvportgroup-527 + dvPG_3729_10.2.82.128_28 + + + l_network_dvportgroup-38430 + dvPG_3595_10.2.163.192_28 + + + l_network_dvportgroup-25836 + dvPG_1850_10.221.7.64_28 + + + l_network_dvportgroup-321 + dvPG_1730_10.2.108.176_28 + + + l_network_dvportgroup-446 + dvPG_4024_10.2.99.176_28 + + + l_network_dvportgroup-696 + dvPG_2350_10.8.34.192_28 + + + l_network_dvportgroup-5792 + dvPG_1946_10.2.118.64_28 + + + l_network_dvportgroup-518 + dvPG_2457_10.2.10.8_29 + + + l_network_dvportgroup-218 + dvPG_1739_10.2.109.144_28 + + + l_network_dvportgroup-258 + dvPG_3760_10.2.86.128_28 + + + l_network_dvportgroup-10796 + dvPG_1949_10.2.119.112_28 + + + l_network_dvportgroup-598 + dvPG_4047_10.2.100.224_28 + + + l_network_dvportgroup-270 + dvPG_1741_10.2.109.176_28 + + + l_network_dvportgroup-38898 + dvPG_3361_10.8.137.160_29 + + + l_network_dvportgroup-28651 + dvPG_3962_10.2.123.176_28 + + + l_network_dvportgroup-44361 + dvPG_3510_10.2.165.32_28 + + + l_network_dvportgroup-607 + dvPG_2401_10.2.133.0_26 + + + l_network_dvportgroup-39567 + dvPG_3821_10.2.93.80_28 + + + l_network_dvportgroup-505 + dvPG_3935_10.2.97.192_28 + + + l_network_dvportgroup-19865 + dvPG_3438_10.2.122.144_28 + + + l_network_dvportgroup-21083 + dvPG_3442_10.2.122.208_28 + + + l_network_dvportgroup-736 + dvPG_3938_10.2.98.112_28 + + + l_network_dvportgroup-37207 + dvPG_3363_10.8.137.176_29 + + + l_network_dvportgroup-223 + dvPG_0086_10.8.38.0_24 + + + l_network_dvportgroup-4542 + dvPG_1935_10.2.115.192_28 + + + l_network_dvportgroup-25879 + dvPG_1913_10.221.10.208_28 + + + l_network_dvportgroup-38899 + dvPG_3705_10.8.139.240_29 + + + l_network_dvportgroup-444 + dvPG_4027_10.2.99.224_28 + + + l_network_dvportgroup-25102 + dvPG_0184_10.2.160.96_28 + + + l_network_dvportgroup-631 + dvPG_3841_10.2.95.128_28 + + + l_network_dvportgroup-29527 + dvPG_3514_10.8.137.112_29 + + + l_network_dvportgroup-210 + dvPG_1763_10.2.110.208_28 + + + l_network_dvportgroup-699 + dvPG_0710_10.8.159.0_24 + + + l_network_dvportgroup-29016 + dvPG_3323_10.2.151.224_28 + + + l_network_dvportgroup-212 + dvPG_3757_10.2.86.96_28 + + + l_network_dvportgroup-714 + dvPG_3863_10.2.97.128_28 + + + l_network_dvportgroup-8824 + dvPG_1962_10.2.119.0_28 + + + l_network_dvportgroup-19961 + dvPG_3439_10.2.122.160_28 + + + l_network_dvportgroup-746 + dvPG_1836_10.2.82.240_28 + + + l_network_dvportgroup-296 + dvPG_1903_10.221.11.128_27 + + + l_network_dvportgroup-525 + dvPG_2479_10.8.71.48_28 + + + l_network_dvportgroup-359 + dvPG_4057_10.2.101.144_28 + + + l_network_dvportgroup-241 + dvPG_3687_10.2.80.32_28 + + + l_network_dvportgroup-12348 + dvPG_1991_10.2.120.80_28 + + + l_network_dvportgroup-365 + dvPG_1812_10.2.113.64_28 + + + l_network_dvportgroup-636 + dvPG_1735_10.2.109.0_28 + + + l_network_dvportgroup-576 + dvPG_3808_10.2.92.128_28 + + + l_network_dvportgroup-25855 + dvPG_1870_10.221.8.128_28 + + + l_network_dvportgroup-23154 + dvPG_3982_10.2.151.64_28 + + + l_network_dvportgroup-25100 + dvPG_170_10.2.160.32_28 + + + l_network_dvportgroup-308 + dvPG_4005_10.2.140.144_28 + + + l_network_dvportgroup-31722 + dvPG_3508_10.2.162.16_28 + + + l_network_dvportgroup-19169 + dvPG_3432_10.2.122.64_28 + + + l_network_dvportgroup-222 + dvPG_3797_10.2.84.208_28 + + + l_network_dvportgroup-42984 + dvPG_119_10.2.121.240_28 + + + l_network_dvportgroup-475 + dvPG_4070_10.2.101.192_28 + + + l_network_dvportgroup-12648 + dvPG_1844_10.2.114.176_28 + + + l_network_dvportgroup-23150 + dvPG_3978_10.2.151.0_28 + + + l_network_dvportgroup-38349 + dvPG_4030_10.2.164.16_28 + + + l_network_dvportgroup-33873 + dvPG_3349_10.2.162.80_28 + + + l_network_dvportgroup-592 + dvPG_3813_10.2.92.208_28 + + + l_network_dvportgroup-422 + dvPG_1790_10.2.111.224_28 + + + l_network_dvportgroup-5788 + dvPG_1942_10.2.118.0_28 + + + l_network_dvportgroup-35054 + dvPG_2486_10.2.162.224_28 + + + l_network_dvportgroup-220 + dvPG_3908_10.2.98.240_28 + + + l_network_dvportgroup-33481 + dvPG_3967_10.2.162.64_28 + + + l_network_dvportgroup-40503 + dvPG_3707_10.2.93.96_28 + + + l_network_dvportgroup-672 + dvPG_1779_10.2.149.0_27 + + + l_network_dvportgroup-44772 + dvPG_3313_10.2.165.48_28 + + + l_network_dvportgroup-273 + dvPG_0711_165.234.152.32_27 + + + l_network_dvportgroup-587 + dvPG_3742_10.2.86.16_28 + + + l_network_dvportgroup-424 + dvPG_4028_10.2.99.240_28 + + + l_network_dvportgroup-698 + dvPG_2349_10.8.34.160_27 + + + l_network_dvportgroup-338 + dvPG_3789_10.2.84.144_28 + + + l_network_dvportgroup-10795 + dvPG_1968_10.2.119.144_28 + + + l_network_dvportgroup-732 + dvPG_3937_10.2.98.96_28 + + + l_network_dvportgroup-11491 + dvPG_1990_10.2.120.0_28 + + + l_network_dvportgroup-694 + dvPG_1787_10.2.112.32_28 + + + l_network_dvportgroup-564 + dvPG_3731_10.2.82.160_28 + + + l_network_dvportgroup-410 + dvPG_1891_10.221.9.128_27 + + + l_network_dvportgroup-544 + dvPG_1716_10.2.107.208_28 + + + l_network_dvportgroup-676 + dvPG_4002_10.2.98.160_28 + + + l_network_dvportgroup-232 + dvPG_1785_10.2.112.0_28 + + + l_network_dvportgroup-549 + dvPG_1718_10.2.107.240_28 + + + l_network_dvportgroup-665 + dvPG_0085_10.11.2.0_24 + + + l_network_dvportgroup-41228 + dvPG_2278_165.234.164.0_27 + + + l_network_dvportgroup-488 + dvPG_3843_10.2.96.128_25 + + + l_network_dvportgroup-509 + dvPG_2395_165.234.44.0_29 + + + l_network_dvportgroup-433 + dvPG_1789_10.2.150.64_26 + + + l_network_dvportgroup-711 + dvPG_3655_10.2.12.80_28 + + + l_network_dvportgroup-412 + dvPG_1799_10.2.112.128_28 + + + l_network_dvportgroup-216 + dvPG_1762_10.2.110.192_28 + + + l_network_dvportgroup-25103 + dvPG_0185_10.2.160.112_28 + + + l_network_dvportgroup-23156 + dvPG_3984_10.2.151.112_28 + + + l_network_dvportgroup-600 + dvPG_3838_10.2.95.112_28 + + + l_network_dvportgroup-25845 + dvPG_1859_10.221.7.208_28 + + + l_network_dvportgroup-471 + dvPG_1793_10.2.112.64_28 + + + l_network_dvportgroup-588 + dvPG_3825_10.2.95.48_28 + + + l_network_dvportgroup-35509 + dvPG_1340_10.2.162.240_28 + + + l_network_dvportgroup-15461 + dvPG_3428_10.2.121.208_28 + + + l_network_dvportgroup-297 + dvPG_1902_10.221.10.64_28 + + + l_network_dvportgroup-25857 + dvPG_1880_10.221.8.224_28 + + + l_network_dvportgroup-214 + dvPG_1738_10.2.109.32_28 + + + l_network_dvportgroup-231 + dvPG_3724_10.2.82.48_28 + + + l_network_dvportgroup-23152 + dvPG_3980_10.2.151.32_28 + + + l_network_dvportgroup-602 + dvPG_1765_10.2.110.224_28 + + + l_network_dvportgroup-693 + dvPG_2321_10.8.139.160_27 + + + l_network_dvportgroup-14568 + dvPG_1848_10.2.115.0_28 + + + l_network_dvportgroup-50962 + dvPG_3891_10.2.121.192_28 + + + l_network_dvportgroup-219 + dvPG_3999_10.2.109.80_28 + + + l_network_dvportgroup-770 + dvPG_4036_10.2.24.0_24 + + + l_network_dvportgroup-4415 + dvPG_1932_10.2.115.144_28 + + + l_datastore_datastore-46548 + VMDOCR1_000_Local + + + l_datastore_datastore-13867 + VMAVAYA1_95_A9K_R_AVAYAGEN + + + l_datastore_datastore-13868 + VMAVAYA1_16_A9K_SYS + + + l_datastore_datastore-13871 + VMTEMPL1_252_A9K_MISC + + + l_datastore_datastore-13872 + VMLINUX1_98_A9K_ISO + + + l_datastore_datastore-13874 + VMLINUX1_104_A9K_R_MMISUC4 + + + l_datastore_datastore-13875 + VMLINUX1_100_A9K_R_DHSSPACES + + + l_datastore_datastore-13876 + VMLINUX1_17_A9K_SYS + + + l_datastore_datastore-13877 + VMLINUX1_105_A9K_R_LEGEND + + + l_datastore_datastore-13878 + VMLINUX1_106_A9K_R_MMISTRUVEN + + + l_datastore_datastore-13881 + VMLINUX1_103_A9K_R_DHSLOADBAL + + + l_datastore_datastore-13886 + VMLINUX1_101_A9K_R_LOGMGT + + + l_datastore_datastore-13894 + VMODM1_112_A9K_R_DHSSPACES + + + l_datastore_datastore-13896 + VMODM1_18_A9K_SYS + + + l_datastore_datastore-13899 + VMORACLE1_19_A9K_SYS + + + l_datastore_datastore-13906 + VMPS1_20_A9K_SYS + + + l_datastore_datastore-13917 + VMSQL1_21_A9K_SYS + + + l_datastore_datastore-13918 + VMSQL1_118_A9K_R_SLRWNDS + + + l_datastore_datastore-13921 + VMTEL1_22_A9K_SYS + + + l_datastore_datastore-13925 + VMWAS1_23_A9K_SYS + + + l_datastore_datastore-13926 + VMWAS1_128_A9K_R_DHSSPACES + + + l_datastore_datastore-13934 + VMWINDOWS1_152_A9K_R_SHRDEMLEXCH + + + l_datastore_datastore-13939 + VMWINDOWS1_137_A9K_R_BNDFIS + + + l_datastore_datastore-13942 + VMWINDOWS1_151_A9K_R_DHSSPACES + + + l_datastore_datastore-13945 + VMWINDOWS1_153_A9K_R_LEGENDRND + + + l_datastore_datastore-13947 + VMWINDOWS1_146_A9K_R_DESWEBEOC + + + l_datastore_datastore-13948 + VMWINDOWS1_157_A9K_R_MMISMOVEIT + + + l_datastore_datastore-13949 + VMWINDOWS1_158_A9K_R_MMISXPRESSION + + + l_datastore_datastore-13950 + VMWINDOWS1_154_A9K_R_MMISCOGNOS + + + l_datastore_datastore-13951 + VMWINDOWS1_155_A9K_R_MMISEDIFECS + + + l_datastore_datastore-13952 + VMWINDOWS1_141_A9K_R_CJISLERMS + + + l_datastore_datastore-13953 + VMWINDOWS1_142_A9K_R_SHRDPPLSFTHE + + + l_datastore_datastore-13954 + VMWINDOWS1_143_A9K_R_SHRDPPLSFTST + + + l_datastore_datastore-13955 + VMWINDOWS1_159_A9K_R_SOSCENINDX + + + l_datastore_datastore-13956 + VMWINDOWS1_140_A9K_R_BNDFUNDTECH + + + l_datastore_datastore-13959 + VMWINDOWS1_144_A9K_R_SHRDDOTNET + + + l_datastore_datastore-13960 + VMWINDOWS1_145_A9K_R_SWDEVTFS + + + l_datastore_datastore-13962 + VMWINDOWS1_138_A9K_R_BNDFISERV + + + l_datastore_datastore-13963 + VMWINDOWS1_24_A9K_SYS + + + l_datastore_datastore-16821 + VMWINDOWS1_134_A9K_R_SHRDEDMSFN + + + l_datastore_datastore-16822 + VMWINDOWS1_135_A9K_R_SHRDEDMSFN + + + l_datastore_datastore-17562 + VMWAS1_126_A9K_R_MMISEDIFECS + + + l_datastore_datastore-46549 + VMDOCR1_000b_Local + + + l_datastore_datastore-21199 + VMAVAYA1_94_A9K_R_SHRDVML + + + l_datastore_datastore-21200 + VMLINUX1_107_A9K_R_LDAPTDS + + + l_datastore_datastore-21201 + VMLINUX1_108_A9K_R_SKLM + + + l_datastore_datastore-21202 + VMLINUX1_109_A9K_R_LEGEND + + + l_datastore_datastore-21204 + VMORACLE1_115_A9K_R_MMISTRUVEN + + + l_datastore_datastore-21205 + VMSQL1_116_A9K_R_PWDST + + + l_datastore_datastore-21206 + VMSQL1_117_A9K_R_SHRDSQL + + + l_datastore_datastore-21207 + VMWINDOWS1_133_A9K_R_BNDBONDBNK + + + l_datastore_datastore-21208 + VMWINDOWS1_163_A9K_R_BNDCALYX + + + l_datastore_datastore-21209 + VMWINDOWS1_164_A9K_R_BNDJRPT + + + l_datastore_datastore-21210 + VMWINDOWS1_188_A9K_R_BNDHELMS + + + l_datastore_datastore-21211 + VMWINDOWS1_189_A9K_R_BNDMFA + + + l_datastore_datastore-21212 + VMWINDOWS1_190_A9K_R_BNDPBOWES + + + l_datastore_datastore-21213 + VMWINDOWS1_207_A9K_R_BNDSHRDAPP + + + l_datastore_datastore-21214 + VMWINDOWS1_208_A9K_R_BNDSHRDAPPNT + + + l_datastore_datastore-21215 + VMWINDOWS1_209_A9K_R_BNDSQL + + + l_datastore_datastore-21216 + VMWINDOWS1_228_A9K_R_DHSOPNSCN + + + l_datastore_datastore-21217 + VMWINDOWS1_229_A9K_R_DHSMEDICLM + + + l_datastore_datastore-21218 + VMWINDOWS1_232_A9K_R_DHSORCHARD + + + l_datastore_datastore-21219 + VMWINDOWS1_233_A9K_R_DOHSHRDAPP + + + l_datastore_datastore-21220 + VMWINDOWS1_234_A9K_R_DOHFOODSAFE + + + l_datastore_datastore-21221 + VMWINDOWS1_235_A9K_R_SHRDEMLRFX + + + l_datastore_datastore-21222 + VMWINDOWS1_236_A9K_R_WSIFORMS + + + l_datastore_datastore-21223 + VMWINDOWS1_244_A9K_R_WSIITSM + + + l_datastore_datastore-21224 + VMWINDOWS1_245_A9K_R_WSIORARPT + + + l_datastore_datastore-21225 + VMWINDOWS1_246_A9K_R_WSISHRDAPP + + + l_datastore_datastore-26831 + VMLINUX1_129_A9K_R_MMISSIMSAM + + + l_datastore_datastore-34384 + VMPS1_48_A9K_R + + + l_datastore_datastore-34385 + VMPS1_49_A9K_R + + + l_datastore_datastore-34386 + VMPS1_50_A9K_R + + + l_datastore_datastore-34387 + VMPS1_51_A9K_R + + + l_datastore_datastore-34388 + VMPS1_52_A9K_R + + + l_datastore_datastore-34389 + VMPS1_53_A9K_R + + + l_datastore_datastore-39645 + VMLINUX1_110_V5K_AWS + + + l_datastore_datastore-39646 + VMWINDOWS1_161_V5K_SECDVR + + + l_datastore_datastore-39647 + VMWINDOWS1_160_V5K_HPNVID + + + l_datastore_datastore-40136 + VMLINUX1_111_V5KARCH_DHS + + + l_datastore_datastore-40928 + VMLINUX1_102_A9K_R_SECURITY + + + l_datastore_datastore-43568 + VMWINDOWS1_123_V5K_SHS + + + l_datastore_datastore-44914 + VMWINDOWS1_156_A9K_R_SVCNOW + + + l_datastore_datastore-45943 + VMWINDOWS1_125_V5K_SCRATCH + + + l_datastore_datastore-48316 + VMLINUX1_55_V5K_SECLOG + + + l_datastore_datastore-48317 + VMLINUX1_56_V5K_SECLOG + + + l_datastore_datastore-48318 + VMLINUX1_67_V5K_SECLOG + + + l_datastore_datastore-48319 + VMLINUX1_68_V5K_SECLOG + + + l_datastore_datastore-48320 + VMLINUX1_242_V5K_ELASTIC + + + l_datastore_datastore-48321 + VMLINUX1_243_V5K_ELASTIC + + + l_datastore_datastore-49220 + VMLINUX1_25_V5K_SECLOG + + + l_datastore_datastore-49221 + VMLINUX1_35_V5K_SECLOG + + + l_datastore_datastore-49222 + VMLINUX1_38_V5K_SECLOG + + + l_datastore_datastore-49223 + VMLINUX1_54_V5K_SECLOG + + + l_datastore_datastore-49224 + VMLINUX1_57_V5K_ELASTIC + + + l_datastore_datastore-49225 + VMLINUX1_66_V5K_ELASTIC + + + l_datastore_datastore-49226 + VMLINUX1_71_V5K_ELASTIC + + + l_datastore_datastore-49227 + VMLINUX1_96_V5K_ELASTIC + + + l_datastore_datastore-49228 + VMLINUX1_99_V5K_ELASTIC + + + l_datastore_datastore-49229 + VMLINUX1_127_V5K_ELASTIC + + + l_datastore_datastore-49230 + VMLINUX1_136_V5K_ELASTIC + + + l_datastore_datastore-49231 + VMLINUX1_139_V5K_ELASTIC + + + l_datastore_datastore-49232 + VMLINUX1_162_V5K_ELASTIC + + + l_datastore_datastore-49233 + VMLINUX1_167_V5K_ELASTIC + + + l_datastore_datastore-49234 + VMLINUX1_170_V5K_ELASTIC + + + l_datastore_datastore-49235 + VMLINUX1_193_V5K_ELASTIC + + + l_datastore_datastore-49236 + VMLINUX1_196_V5K_ELASTIC + + + l_datastore_datastore-49237 + VMLINUX1_211_V5K_ELASTIC + + + l_datastore_datastore-49238 + VMLINUX1_219_V5K_ELASTIC + + + l_datastore_datastore-49239 + VMLINUX1_221_V5K_ELASTIC + + + l_datastore_datastore-49240 + VMLINUX1_238_V5K_GRAYLOG + + + l_datastore_datastore-49241 + VMLINUX1_240_V5K_GRAYLOG + + + l_datastore_datastore-49606 + VMWINDOWS1_39_V5K_FS + + + l_datastore_datastore-51196 + VMTEMPL1_008_FS92_MISC + + + l_datastore_datastore-51197 + VMWINDOWS1_100_FS92_Gen + + + l_datastore_datastore-51198 + VMWINDOWS1_101_FS92_Gen + + + l_datastore_datastore-51199 + VMWINDOWS1_102_FS92_Gen + + + l_datastore_datastore-51200 + VMWINDOWS1_103_FS92_Gen + + + l_datastore_datastore-51201 + VMWINDOWS1_104_FS92_Gen + + + l_datastore_datastore-51202 + VMWINDOWS1_171_FS92_SQL + + + l_datastore_datastore-51203 + VMWINDOWS1_172_FS92_SQL + + + l_datastore_datastore-51204 + VMWINDOWS1_173_FS92_SQL + + + l_datastore_datastore-51205 + VMWINDOWS1_174_FS92_SQL + + + l_datastore_datastore-51324 + VMSQL1_040_FS92_ABR_PWDST + + + l_datastore_datastore-51325 + VMSQL1_041_FS92_ABR_SHRDSQL + + + l_datastore_datastore-51326 + VMSQL1_042_FS92_ABR_SLRWNDS + + + l_datastore_datastore-51327 + VMSQL1_043_FS92_TAX + + + l_datastore_datastore-51328 + VMSQL1_044_FS92_TAX + + + l_datastore_datastore-51329 + VMSQL1_045_FS92_DOTMV + + + l_datastore_datastore-51330 + VMSQL1_046_FS92 + + + l_datastore_datastore-51331 + VMSQL1_047_FS92 + + + l_datastore_datastore-51332 + VMSQL1_048_FS92 + + + l_datastore_datastore-51333 + VMSQL1_049_FS92 + + + l_datastore_datastore-51334 + VMSQL1_050_FS92 + + + l_datastore_datastore-51335 + VMSQL1_051_FS92 + + + l_datastore_datastore-51336 + VMSQL1_052_FS92 + + + l_datastore_datastore-51338 + VMWINDOWS1_105_FS92_Gen + + + l_datastore_datastore-51339 + VMWINDOWS1_227_FS92_ABR_SKYPE + + + l_datastore_datastore-51340 + VMWINDOWS1_095_FS92_ABR + + + l_datastore_datastore-51341 + VMWINDOWS1_121_FS92_ABR_MMISMOVEIT + + + l_datastore_datastore-51342 + VMWINDOWS1_122_FS92_ABR_MMISXPRESSION + + + l_datastore_datastore-51343 + VMWINDOWS1_124_FS92_ABR_SOSCENINDX + + + l_datastore_datastore-51344 + VMWINDOWS1_126_FS92_ABR_BNDCALYX + + + l_datastore_datastore-51345 + VMWINDOWS1_165_FS92_ABR_LEGENDRND + + + l_datastore_datastore-51347 + VMWINDOWS1_168_FS92_ABR_MMISEDIFECS + + + l_datastore_datastore-51348 + VMWINDOWS1_169_FS92_ABR_SVCNOW + + + l_datastore_datastore-51349 + VMWINDOWS1_175_FS92_ABR_SHRDEDMSFN + + + l_datastore_datastore-51350 + VMWINDOWS1_176_FS92_ABR_SHRDEDMSFN + + + l_datastore_datastore-51351 + VMWINDOWS1_177_FS92_ABR_BNDBONDBNK + + + l_datastore_datastore-51352 + VMWINDOWS1_178_FS92_ABR_BNDFIS + + + l_datastore_datastore-51353 + VMWINDOWS1_179_FS92_ABR_BNDFISERV + + + l_datastore_datastore-51354 + VMWINDOWS1_180_FS92_ABR_BNDFUNDTECH + + + l_datastore_datastore-51355 + VMWINDOWS1_181_FS92_ABR_CJISLERMS + + + l_datastore_datastore-51356 + VMWINDOWS1_182_FS92_ABR_SHRDPPLSFTHE + + + l_datastore_datastore-51358 + VMWINDOWS1_184_FS92_ABR_SHRDDOTNET + + + l_datastore_datastore-51359 + VMWINDOWS1_185_FS92_ABR_SWDEVTFS + + + l_datastore_datastore-51360 + VMWINDOWS1_186_FS92_ABR_DESWEBEOC + + + l_datastore_datastore-51361 + VMWINDOWS1_187_FS92_ABR_BNDHELMS + + + l_datastore_datastore-51362 + VMWINDOWS1_191_FS92_ABR_DHSSPACES + + + l_datastore_datastore-51363 + VMWINDOWS1_192_FS92_ABR_SHRDEMLEXCH + + + l_datastore_datastore-51364 + VMWINDOWS1_194_FS92_ABR_BNDJRPT + + + l_datastore_datastore-51365 + VMWINDOWS1_195_FS92_ABR_BNDMFA + + + l_datastore_datastore-51366 + VMWINDOWS1_210_FS92_ABR_BNDPBOWES + + + l_datastore_datastore-51367 + VMWINDOWS1_212_FS92_ABR_BNDSHRDAPP + + + l_datastore_datastore-51368 + VMWINDOWS1_213_FS92_ABR_BNDSHRDAPPNT + + + l_datastore_datastore-51369 + VMWINDOWS1_214_FS92_ABR_BNDSQL + + + l_datastore_datastore-51370 + VMWINDOWS1_215_FS92_ABR_DHSOPNSCN + + + l_datastore_datastore-51371 + VMWINDOWS1_216_FS92_ABR_DHSMEDICLM + + + l_datastore_datastore-51373 + VMWINDOWS1_218_FS92_ABR_DOHSHRDAPP + + + l_datastore_datastore-51374 + VMWINDOWS1_220_FS92_ABR_DOHFOODSAFE + + + l_datastore_datastore-51375 + VMWINDOWS1_222_FS92_ABR_SHRDEMLRFX + + + l_datastore_datastore-51376 + VMWINDOWS1_223_FS92_ABR_WSIFORMS + + + l_datastore_datastore-51377 + VMWINDOWS1_224_FS92_ABR_WSIITSM + + + l_datastore_datastore-51378 + VMWINDOWS1_225_FS92_ABR_WSIORARPT + + + l_datastore_datastore-51379 + VMWINDOWS1_226_FS92_ABR_WSISHRDAPP + + + l_datastore_datastore-51461 + VMWINDOWS1_183_FS92_ABR_SHRDPPLSFTST + + + l_datastore_datastore-51729 + VMAVAYA1_012_FS92_ABR_General + + + l_datastore_datastore-51730 + VMAVAYA1_013_FS92_ABR_SHRDVML + + + l_datastore_datastore-51731 + VMAVAYA1_014_FS92 + + + l_datastore_datastore-51732 + VMAVAYA1_015_FS92 + + + l_datastore_datastore-51733 + VMODM1_019_FS92_ABR_SPACES + + + l_datastore_datastore-51734 + VMODM1_022_FS92_DHS + + + l_datastore_datastore-51735 + VMORACLE1_023_FS92_General + + + l_datastore_datastore-51736 + VMORACLE1_024_FS92_ABR_MMISTRUVEN + + + l_datastore_datastore-51737 + VMPS1_018_FS92_General + + + l_datastore_datastore-51738 + VMPS1_087_FS92 + + + l_datastore_datastore-51739 + VMPS1_088_FS92 + + + l_datastore_datastore-51740 + VMPS1_089_FS92 + + + l_datastore_datastore-51741 + VMPS1_090_FS92 + + + l_datastore_datastore-51742 + VMTEL1_026_FS92_VBRICK + + + l_datastore_datastore-51743 + VMTEL1_027_FS92 + + + l_datastore_datastore-51744 + VMTEL1_028_FS92 + + + l_datastore_datastore-51745 + VMWAS1_032_FS92_ABR_MMISEDIFECS + + + l_datastore_datastore-51746 + VMWAS1_033_FS92_ABR_DHSSPACES + + + l_datastore_datastore-51747 + VMWAS1_036_FS92 + + + l_datastore_datastore-51748 + VMWAS1_037_FS92 + + + l_datastore_datastore-51749 + VMLINUX1_058_FS92_SATELLITE + + + l_datastore_datastore-51750 + VMLINUX1_059_FS92_TENABLE + + + l_datastore_datastore-51751 + VMLINUX1_060_FS92_ASR + + + l_datastore_datastore-51752 + VMLINUX1_061_FS92_ISO + + + l_datastore_datastore-51753 + VMLINUX1_062_FS92 + + + l_datastore_datastore-51754 + VMLINUX1_063_FS92 + + + l_datastore_datastore-51755 + VMLINUX1_064_FS92 + + + l_datastore_datastore-51756 + VMLINUX1_065_FS92 + + + l_datastore_datastore-51757 + VMLINUX1_072_FS92_ABR_DHSSPACES + + + l_datastore_datastore-51758 + VMLINUX1_073_FS92_ABR_LOGMGT + + + l_datastore_datastore-51759 + VMLINUX1_074_FS92_ABR_SECURITY + + + l_datastore_datastore-51760 + VMLINUX1_075_FS92_ABR_DHSLOADBAL + + + l_datastore_datastore-51761 + VMLINUX1_076_FS92_ABR_MMISUC4 + + + l_datastore_datastore-51762 + VMLINUX1_077_FS92_ABR_LEGEND + + + l_datastore_datastore-51763 + VMLINUX1_078_FS92_ABR_MMISTRUVEN + + + l_datastore_datastore-51764 + VMLINUX1_079_FS92_ABR_LDAPTDS + + + l_datastore_datastore-51765 + VMLINUX1_080_FS92_ABR_SKLM + + + l_datastore_datastore-51766 + VMLINUX1_081_FS92_ABR_LEGEND + + + l_datastore_datastore-51767 + VMLINUX1_082_FS92_ABR_MMISSIMSAM + + + l_datastore_datastore-51777 + VMWINDOWS1_197_FS92_ASR + + + l_datastore_datastore-51778 + VMSCRATCH1_006_FS92 + + + l_datastore_datastore-51779 + VMWINDOWS1_166_FS92_ABR_MMISCOGNOS + + + l_datastore_datastore-51780 + VMWINDOWS1_217_FS92_ABR_DHSORCHARD + + + + + + + + + + true + + l_network_dvportgroup-487 + r_network_dvportgroup-644 + + + l_network_dvportgroup-29143 + r_network_dvportgroup-19478 + + + l_network_dvportgroup-360 + r_network_dvportgroup-328 + + + l_network_dvportgroup-497 + r_network_dvportgroup-629 + + + l_network_dvportgroup-224 + r_network_dvportgroup-599 + + + l_network_dvportgroup-236 + r_network_dvportgroup-262 + + + l_network_dvportgroup-638 + r_network_dvportgroup-394 + + + l_network_dvportgroup-666 + r_network_dvportgroup-439 + + + l_network_dvportgroup-223 + r_network_dvportgroup-197 + + + l_network_dvportgroup-745 + r_network_dvportgroup-499 + + + l_network_dvportgroup-358 + r_network_dvportgroup-539 + + + l_network_dvportgroup-737 + r_network_dvportgroup-426 + + + l_network_dvportgroup-265 + r_network_dvportgroup-183 + + + l_network_dvportgroup-667 + r_network_dvportgroup-646 + + + l_network_dvportgroup-740 + r_network_dvportgroup-435 + + + l_network_dvportgroup-739 + r_network_dvportgroup-464 + + + l_network_dvportgroup-624 + r_network_dvportgroup-456 + + + l_network_dvportgroup-228 + r_network_dvportgroup-677 + + + l_network_dvportgroup-635 + r_network_dvportgroup-390 + + + l_network_dvportgroup-647 + r_network_dvportgroup-689 + + + l_network_dvportgroup-26895 + r_network_dvportgroup-18302 + + + l_network_dvportgroup-252 + r_network_dvportgroup-607 + + + l_network_dvportgroup-501 + r_network_dvportgroup-424 + + + l_network_dvportgroup-29071 + r_network_dvportgroup-19447 + + + l_network_dvportgroup-611 + r_network_dvportgroup-653 + + + l_network_dvportgroup-636 + r_network_dvportgroup-392 + + + l_network_dvportgroup-286 + r_network_dvportgroup-632 + + + l_network_dvportgroup-609 + r_network_dvportgroup-414 + + + l_network_dvportgroup-243 + r_network_dvportgroup-429 + + + l_network_dvportgroup-618 + r_network_dvportgroup-608 + + + l_network_dvportgroup-673 + r_network_dvportgroup-609 + + + l_network_dvportgroup-25842 + r_network_dvportgroup-17750 + + + l_network_dvportgroup-655 + r_network_dvportgroup-229 + + + l_network_dvportgroup-733 + r_network_dvportgroup-453 + + + l_network_dvportgroup-715 + r_network_dvportgroup-513 + + + l_network_dvportgroup-530 + r_network_dvportgroup-706 + + + l_network_dvportgroup-699 + r_network_dvportgroup-603 + + + l_network_dvportgroup-318 + r_network_dvportgroup-534 + + + l_network_dvportgroup-712 + r_network_dvportgroup-686 + + + l_network_dvportgroup-491 + r_network_dvportgroup-462 + + + l_network_dvportgroup-642 + r_network_dvportgroup-417 + + + l_network_dvportgroup-25051 + r_network_dvportgroup-17308 + + + l_network_dvportgroup-634 + r_network_dvportgroup-697 + + + l_network_dvportgroup-227 + r_network_dvportgroup-593 + + + l_network_dvportgroup-648 + r_network_dvportgroup-494 + + + l_network_dvportgroup-486 + r_network_dvportgroup-648 + + + l_network_dvportgroup-316 + r_network_dvportgroup-528 + + + l_network_dvportgroup-727 + r_network_dvportgroup-470 + + + l_network_dvportgroup-775 + r_network_dvportgroup-735 + + + l_network_dvportgroup-314 + r_network_dvportgroup-321 + + + l_network_dvportgroup-544 + r_network_dvportgroup-349 + + + l_network_dvportgroup-564 + r_network_dvportgroup-590 + + + l_network_dvportgroup-693 + r_network_dvportgroup-614 + + + l_network_dvportgroup-527 + r_network_dvportgroup-612 + + + l_network_dvportgroup-573 + r_network_dvportgroup-696 + + + l_network_dvportgroup-546 + r_network_dvportgroup-348 + + + l_network_dvportgroup-210 + r_network_dvportgroup-557 + + + l_network_dvportgroup-662 + r_network_dvportgroup-359 + + + l_network_dvportgroup-399 + r_network_dvportgroup-657 + + + l_network_dvportgroup-572 + r_network_dvportgroup-694 + + + l_network_dvportgroup-562 + r_network_dvportgroup-594 + + + l_network_dvportgroup-571 + r_network_dvportgroup-693 + + + l_network_dvportgroup-535 + r_network_dvportgroup-703 + + + l_network_dvportgroup-292 + r_network_dvportgroup-695 + + + l_network_dvportgroup-231 + r_network_dvportgroup-700 + + + l_network_dvportgroup-672 + r_network_dvportgroup-459 + + + l_network_dvportgroup-481 + r_network_dvportgroup-431 + + + l_network_dvportgroup-14569 + r_network_dvportgroup-10395 + + + l_network_dvportgroup-25879 + r_network_dvportgroup-17742 + + + l_network_dvportgroup-226 + r_network_dvportgroup-679 + + + l_network_dvportgroup-233 + r_network_dvportgroup-642 + + + l_network_dvportgroup-583 + r_network_dvportgroup-654 + + + l_network_dvportgroup-500 + r_network_dvportgroup-675 + + + l_network_dvportgroup-496 + r_network_dvportgroup-678 + + + l_network_dvportgroup-567 + r_network_dvportgroup-623 + + + l_network_dvportgroup-533 + r_network_dvportgroup-616 + + + l_network_dvportgroup-565 + r_network_dvportgroup-226 + + + l_network_dvportgroup-570 + r_network_dvportgroup-218 + + + l_network_dvportgroup-5792 + r_network_dvportgroup-3961 + + + l_network_dvportgroup-587 + r_network_dvportgroup-540 + + + l_network_dvportgroup-260 + r_network_dvportgroup-215 + + + l_network_dvportgroup-690 + r_network_dvportgroup-323 + + + l_network_dvportgroup-506 + r_network_dvportgroup-376 + + + l_network_dvportgroup-736 + r_network_dvportgroup-449 + + + l_network_dvportgroup-23209 + r_network_dvportgroup-16326 + + + l_network_dvportgroup-215 + r_network_dvportgroup-484 + + + l_network_dvportgroup-25868 + r_network_dvportgroup-17731 + + + l_network_dvportgroup-276 + r_network_dvportgroup-427 + + + l_network_dvportgroup-674 + r_network_dvportgroup-339 + + + l_network_dvportgroup-676 + r_network_dvportgroup-340 + + + l_network_dvportgroup-668 + r_network_dvportgroup-341 + + + l_network_dvportgroup-671 + r_network_dvportgroup-342 + + + l_network_dvportgroup-304 + r_network_dvportgroup-705 + + + l_network_dvportgroup-397 + r_network_dvportgroup-181 + + + l_network_dvportgroup-683 + r_network_dvportgroup-458 + + + l_network_dvportgroup-421 + r_network_dvportgroup-444 + + + l_network_dvportgroup-423 + r_network_dvportgroup-446 + + + l_network_dvportgroup-36736 + r_network_dvportgroup-24253 + + + l_network_dvportgroup-422 + r_network_dvportgroup-402 + + + l_network_dvportgroup-27876 + r_network_dvportgroup-18846 + + + l_network_dvportgroup-438 + r_network_dvportgroup-401 + + + l_network_dvportgroup-439 + r_network_dvportgroup-327 + + + l_network_dvportgroup-428 + r_network_dvportgroup-175 + + + l_network_dvportgroup-238 + r_network_dvportgroup-191 + + + l_network_dvportgroup-432 + r_network_dvportgroup-366 + + + l_network_dvportgroup-379 + r_network_dvportgroup-550 + + + l_network_dvportgroup-389 + r_network_dvportgroup-466 + + + l_network_dvportgroup-25862 + r_network_dvportgroup-17725 + + + l_network_dvportgroup-395 + r_network_dvportgroup-270 + + + l_network_dvportgroup-25876 + r_network_dvportgroup-17739 + + + l_network_dvportgroup-257 + r_network_dvportgroup-237 + + + l_network_dvportgroup-711 + r_network_dvportgroup-176 + + + l_network_dvportgroup-25163 + r_network_dvportgroup-17367 + + + l_network_dvportgroup-4541 + r_network_dvportgroup-3579 + + + l_network_dvportgroup-4542 + r_network_dvportgroup-3580 + + + l_network_dvportgroup-513 + r_network_dvportgroup-663 + + + l_network_dvportgroup-45382 + r_network_dvportgroup-28699 + + + l_network_dvportgroup-615 + r_network_dvportgroup-422 + + + l_network_dvportgroup-700 + r_network_dvportgroup-639 + + + l_network_dvportgroup-696 + r_network_dvportgroup-641 + + + l_network_dvportgroup-493 + r_network_dvportgroup-628 + + + l_network_dvportgroup-516 + r_network_dvportgroup-223 + + + l_network_dvportgroup-526 + r_network_dvportgroup-221 + + + l_network_dvportgroup-687 + r_network_dvportgroup-627 + + + l_network_dvportgroup-512 + r_network_dvportgroup-583 + + + l_network_dvportgroup-525 + r_network_dvportgroup-208 + + + l_network_dvportgroup-27878 + r_network_dvportgroup-18848 + + + l_network_dvportgroup-29141 + r_network_dvportgroup-19476 + + + l_network_dvportgroup-25160 + r_network_dvportgroup-17364 + + + l_network_dvportgroup-19962 + r_network_dvportgroup-13984 + + + l_network_dvportgroup-25161 + r_network_dvportgroup-17365 + + + l_network_dvportgroup-25162 + r_network_dvportgroup-17366 + + + l_network_dvportgroup-372 + r_network_dvportgroup-584 + + + l_network_dvportgroup-427 + r_network_dvportgroup-319 + + + l_network_dvportgroup-461 + r_network_dvportgroup-246 + + + l_network_dvportgroup-456 + r_network_dvportgroup-248 + + + l_network_dvportgroup-374 + r_network_dvportgroup-408 + + + l_network_dvportgroup-453 + r_network_dvportgroup-344 + + + l_network_dvportgroup-34446 + r_network_dvportgroup-22324 + + + l_network_dvportgroup-449 + r_network_dvportgroup-352 + + + l_network_dvportgroup-475 + r_network_dvportgroup-200 + + + l_network_dvportgroup-656 + r_network_dvportgroup-355 + + + l_network_dvportgroup-659 + r_network_dvportgroup-353 + + + l_network_dvportgroup-551 + r_network_dvportgroup-465 + + + l_network_dvportgroup-41233 + r_network_dvportgroup-26745 + + + l_network_dvportgroup-287 + r_network_dvportgroup-368 + + + l_network_dvportgroup-704 + r_network_dvportgroup-308 + + + l_network_dvportgroup-12261 + r_network_dvportgroup-8581 + + + l_network_dvportgroup-15847 + r_network_dvportgroup-11483 + + + l_network_dvportgroup-738 + r_network_dvportgroup-438 + + + l_network_dvportgroup-514 + r_network_dvportgroup-606 + + + l_network_dvportgroup-25875 + r_network_dvportgroup-17738 + + + l_network_dvportgroup-222 + r_network_dvportgroup-219 + + + l_network_dvportgroup-464 + r_network_dvportgroup-201 + + + l_network_dvportgroup-643 + r_network_dvportgroup-384 + + + l_network_dvportgroup-467 + r_network_dvportgroup-520 + + + l_network_dvportgroup-474 + r_network_dvportgroup-519 + + + l_network_dvportgroup-473 + r_network_dvportgroup-518 + + + l_network_dvportgroup-457 + r_network_dvportgroup-381 + + + l_network_dvportgroup-724 + r_network_dvportgroup-455 + + + l_network_dvportgroup-731 + r_network_dvportgroup-451 + + + l_network_dvportgroup-345 + r_network_dvportgroup-279 + + + l_network_dvportgroup-347 + r_network_dvportgroup-278 + + + l_network_dvportgroup-19074 + r_network_dvportgroup-12953 + + + l_network_dvportgroup-447 + r_network_dvportgroup-400 + + + l_network_dvportgroup-273 + r_network_dvportgroup-535 + + + l_network_dvportgroup-770 + r_network_dvportgroup-731 + + + l_network_dvportgroup-25869 + r_network_dvportgroup-17732 + + + l_network_dvportgroup-44772 + r_network_dvportgroup-28386 + + + l_network_dvportgroup-338 + r_network_dvportgroup-386 + + + l_network_dvportgroup-35509 + r_network_dvportgroup-22888 + + + l_network_dvportgroup-38897 + r_network_dvportgroup-25456 + + + l_network_dvportgroup-25864 + r_network_dvportgroup-17727 + + + l_network_dvportgroup-36169 + r_network_dvportgroup-23911 + + + l_network_dvportgroup-26893 + r_network_dvportgroup-18300 + + + l_network_dvportgroup-29018 + r_network_dvportgroup-19419 + + + l_network_dvportgroup-29019 + r_network_dvportgroup-19420 + + + l_network_dvportgroup-37206 + r_network_dvportgroup-24535 + + + l_network_dvportgroup-38900 + r_network_dvportgroup-25459 + + + l_network_dvportgroup-410 + r_network_dvportgroup-275 + + + l_network_dvportgroup-10007 + r_network_dvportgroup-6975 + + + l_network_dvportgroup-25847 + r_network_dvportgroup-17755 + + + l_network_dvportgroup-25838 + r_network_dvportgroup-17746 + + + l_network_dvportgroup-48678 + r_network_dvportgroup-30403 + + + l_network_dvportgroup-25849 + r_network_dvportgroup-17757 + + + l_network_dvportgroup-42818 + r_network_dvportgroup-27526 + + + l_folder_group-v21227 + r_folder_group-v14703 + + + l_folder_group-v21236 + r_folder_group-v14705 + + + l_folder_group-v21594 + r_folder_group-v15380 + + + l_folder_group-v21516 + r_folder_group-v14927 + + + l_folder_group-v21229 + r_folder_group-v14706 + + + l_folder_group-v21231 + r_folder_group-v14697 + + + l_folder_group-v793 + r_folder_group-v118 + + + l_folder_group-v21134 + r_folder_group-v14546 + + + l_folder_group-v21133 + r_folder_group-v14545 + + + l_folder_group-v21135 + r_folder_group-v14547 + + + l_folder_group-v21383 + r_folder_group-v14735 + + + l_folder_group-v792 + r_folder_group-v117 + + + l_folder_group-v21392 + r_folder_group-v14768 + + + l_folder_group-v797 + r_folder_group-v122 + + + l_folder_group-v21230 + r_folder_group-v14698 + + + l_folder_group-v21447 + r_folder_group-v14849 + + + l_folder_group-v796 + r_folder_group-v121 + + + l_folder_group-v21388 + r_folder_group-v14752 + + + l_folder_group-v21379 + r_folder_group-v14724 + + + l_folder_group-v21232 + r_folder_group-v14699 + + + l_folder_group-v21233 + r_folder_group-v14700 + + + l_folder_group-v20501 + r_folder_group-v14557 + + + l_folder_group-v21394 + r_folder_group-v14783 + + + l_folder_group-v20471 + r_folder_group-v14185 + + + l_folder_group-v21228 + r_folder_group-v14704 + + + l_folder_group-v21513 + r_folder_group-v14924 + + + l_folder_group-v21591 + r_folder_group-v15383 + + + l_folder_group-v808 + r_folder_group-v133 + + + l_folder_group-v21136 + r_folder_group-v14548 + + + l_folder_group-v20491 + r_folder_group-v14210 + + + l_folder_group-v20503 + r_folder_group-v14204 + + + l_folder_group-v20482 + r_folder_group-v14550 + + + l_folder_group-v817 + r_folder_group-v142 + + + l_folder_group-v20483 + r_folder_group-v14195 + + + l_folder_group-v21139 + r_folder_group-v14551 + + + l_folder_group-v22090 + r_folder_group-v15739 + + + l_folder_group-v21526 + r_folder_group-v14937 + + + l_folder_group-v20478 + r_folder_group-v14189 + + + l_folder_group-v20467 + r_folder_group-v14180 + + + l_folder_group-v21226 + r_folder_group-v14702 + + + l_folder_group-v21511 + r_folder_group-v14922 + + + l_folder_group-v21534 + r_folder_group-v15069 + + + l_folder_group-v20498 + r_folder_group-v14220 + + + l_folder_group-v21528 + r_folder_group-v14939 + + + l_folder_group-v20487 + r_folder_group-v14202 + + + l_folder_group-v20490 + r_folder_group-v14209 + + + l_folder_group-v20502 + r_folder_group-v14203 + + + l_folder_group-v21535 + r_folder_group-v15070 + + + l_folder_group-v21590 + r_folder_group-v15384 + + + l_folder_group-v21512 + r_folder_group-v14923 + + + l_folder_group-v21538 + r_folder_group-v15123 + + + l_folder_group-v20497 + r_folder_group-v14219 + + + l_folder_group-v22091 + r_folder_group-v15738 + + + l_folder_group-v21529 + r_folder_group-v14940 + + + l_folder_group-v20488 + r_folder_group-v14205 + + + l_folder_group-v21593 + r_folder_group-v15381 + + + l_folder_group-v21515 + r_folder_group-v14926 + + + l_folder_group-v20492 + r_folder_group-v14212 + + + l_folder_group-v20504 + r_folder_group-v14206 + + + l_folder_group-v20464 + r_folder_group-v14177 + + + l_folder_group-v21595 + r_folder_group-v15379 + + + l_folder_group-v21517 + r_folder_group-v14928 + + + l_folder_group-v20505 + r_folder_group-v14207 + + + l_folder_group-v21518 + r_folder_group-v14929 + + + l_folder_group-v21596 + r_folder_group-v15378 + + + l_folder_group-v8303 + r_folder_group-v5862 + + + l_folder_group-v21519 + r_folder_group-v14930 + + + l_folder_group-v21234 + r_folder_group-v14701 + + + l_folder_group-v21148 + r_folder_group-v14560 + + + l_folder_group-v20475 + r_folder_group-v14190 + + + l_folder_group-v818 + r_folder_group-v143 + + + l_folder_group-v21450 + r_folder_group-v14851 + + + l_folder_group-v811 + r_folder_group-v136 + + + l_folder_group-v21536 + r_folder_group-v15071 + + + l_folder_group-v20499 + r_folder_group-v14221 + + + l_folder_group-v21527 + r_folder_group-v14938 + + + l_folder_group-v20496 + r_folder_group-v14217 + + + l_folder_group-v21387 + r_folder_group-v14748 + + + l_folder_group-v20507 + r_folder_group-v14218 + + + l_folder_group-v20451 + r_folder_group-v14164 + + + l_folder_group-v20450 + r_folder_group-v14163 + + + l_folder_group-v20449 + r_folder_group-v14162 + + + l_folder_group-v21589 + r_folder_group-v15385 + + + l_folder_group-v20448 + r_folder_group-v14161 + + + l_folder_group-v21588 + r_folder_group-v15386 + + + l_folder_group-v20447 + r_folder_group-v14160 + + + l_folder_group-v20456 + r_folder_group-v14168 + + + l_folder_group-v21531 + r_folder_group-v14942 + + + l_folder_group-v20455 + r_folder_group-v14167 + + + l_folder_group-v21451 + r_folder_group-v14852 + + + l_folder_group-v20466 + r_folder_group-v14179 + + + l_folder_group-v21530 + r_folder_group-v14941 + + + l_folder_group-v809 + r_folder_group-v134 + + + l_folder_group-v21142 + r_folder_group-v14554 + + + l_folder_group-v20485 + r_folder_group-v14197 + + + l_folder_group-v21390 + r_folder_group-v14766 + + + l_folder_group-v24865 + r_folder_group-v16479 + + + l_folder_group-v21391 + r_folder_group-v14767 + + + l_folder_group-v21385 + r_folder_group-v14739 + + + l_folder_group-v21386 + r_folder_group-v14740 + + + l_folder_group-v21446 + r_folder_group-v14848 + + + l_folder_group-v21144 + r_folder_group-v14556 + + + l_folder_group-v21143 + r_folder_group-v14555 + + + l_folder_group-v20473 + r_folder_group-v14188 + + + l_folder_group-v21449 + r_folder_group-v14850 + + + l_folder_group-v805 + r_folder_group-v130 + + + l_folder_group-v21393 + r_folder_group-v14782 + + + l_folder_group-v806 + r_folder_group-v131 + + + l_folder_group-v807 + r_folder_group-v132 + + + l_folder_group-v21147 + r_folder_group-v14559 + + + l_folder_group-v21537 + r_folder_group-v15097 + + + l_folder_group-v20489 + r_folder_group-v14208 + + + l_folder_group-v21592 + r_folder_group-v15382 + + + l_folder_group-v20506 + r_folder_group-v14211 + + + l_folder_group-v21396 + r_folder_group-v14788 + + + l_folder_group-v21980 + r_folder_group-v15718 + + + l_folder_group-v34614 + r_folder_group-v26551 + + + l_folder_group-v20493 + r_folder_group-v14213 + + + l_folder_group-v21522 + r_folder_group-v14933 + + + l_folder_group-v814 + r_folder_group-v139 + + + l_folder_group-v21943 + r_folder_group-v15728 + + + l_folder_group-v21524 + r_folder_group-v14935 + + + l_folder_group-v20494 + r_folder_group-v14215 + + + l_folder_group-v21525 + r_folder_group-v14936 + + + l_folder_group-v21382 + r_folder_group-v14730 + + + l_folder_group-v21454 + r_folder_group-v14879 + + + l_folder_group-v21453 + r_folder_group-v14880 + + + l_folder_group-v21452 + r_folder_group-v14881 + + + l_folder_group-v22071 + r_folder_group-v15717 + + + l_folder_group-v22072 + r_folder_group-v15736 + + + l_folder_group-v21977 + r_folder_group-v15737 + + + l_folder_group-v36850 + r_folder_group-v24323 + + + l_folder_group-v26945 + r_folder_group-v15700 + + + l_folder_group-v22055 + r_folder_group-v21859 + + + l_folder_group-v44842 + r_folder_group-v28498 + + + l_resource_resgroup-114 + r_resource_resgroup-76 + + + l_resource_resgroup-102 + r_resource_resgroup-62 + + + l_resource_resgroup-116 + r_resource_resgroup-78 + + + l_resource_resgroup-108 + r_resource_resgroup-68 + + + l_resource_resgroup-112 + r_resource_resgroup-72 + + + l_resource_resgroup-104 + r_resource_resgroup-64 + + + l_resource_resgroup-106 + r_resource_resgroup-66 + + + l_resource_resgroup-110 + r_resource_resgroup-70 + + + l_resource_resgroup-82 + r_resource_resgroup-30885 + + + + false + + r_network_dvportgroup-616 + l_network_dvportgroup-533 + + + r_network_dvportgroup-279 + l_network_dvportgroup-345 + + + r_network_dvportgroup-675 + l_network_dvportgroup-500 + + + r_network_dvportgroup-644 + l_network_dvportgroup-487 + + + r_network_dvportgroup-653 + l_network_dvportgroup-611 + + + r_network_dvportgroup-223 + l_network_dvportgroup-516 + + + r_network_dvportgroup-629 + l_network_dvportgroup-497 + + + r_network_dvportgroup-607 + l_network_dvportgroup-252 + + + r_network_dvportgroup-599 + l_network_dvportgroup-224 + + + r_network_dvportgroup-390 + l_network_dvportgroup-635 + + + r_network_dvportgroup-426 + l_network_dvportgroup-737 + + + r_network_dvportgroup-435 + l_network_dvportgroup-740 + + + r_network_dvportgroup-429 + l_network_dvportgroup-243 + + + r_network_dvportgroup-464 + l_network_dvportgroup-739 + + + r_network_dvportgroup-414 + l_network_dvportgroup-609 + + + r_network_dvportgroup-19447 + l_network_dvportgroup-29071 + + + r_network_dvportgroup-19478 + l_network_dvportgroup-29143 + + + r_network_dvportgroup-646 + l_network_dvportgroup-667 + + + r_network_dvportgroup-593 + l_network_dvportgroup-227 + + + r_network_dvportgroup-609 + l_network_dvportgroup-673 + + + r_network_dvportgroup-197 + l_network_dvportgroup-223 + + + r_network_dvportgroup-689 + l_network_dvportgroup-647 + + + r_network_dvportgroup-18302 + l_network_dvportgroup-26895 + + + r_network_dvportgroup-25456 + l_network_dvportgroup-38897 + + + r_network_dvportgroup-229 + l_network_dvportgroup-655 + + + r_network_dvportgroup-623 + l_network_dvportgroup-567 + + + r_network_dvportgroup-677 + l_network_dvportgroup-228 + + + r_network_dvportgroup-3580 + l_network_dvportgroup-4542 + + + r_network_dvportgroup-499 + l_network_dvportgroup-745 + + + r_network_dvportgroup-513 + l_network_dvportgroup-715 + + + r_network_dvportgroup-30403 + l_network_dvportgroup-48678 + + + r_network_dvportgroup-215 + l_network_dvportgroup-260 + + + r_network_dvportgroup-226 + l_network_dvportgroup-565 + + + r_network_dvportgroup-608 + l_network_dvportgroup-618 + + + r_network_dvportgroup-392 + l_network_dvportgroup-636 + + + r_network_dvportgroup-417 + l_network_dvportgroup-642 + + + r_network_dvportgroup-439 + l_network_dvportgroup-666 + + + r_network_dvportgroup-612 + l_network_dvportgroup-527 + + + r_network_dvportgroup-218 + l_network_dvportgroup-570 + + + r_network_dvportgroup-275 + l_network_dvportgroup-410 + + + r_network_dvportgroup-679 + l_network_dvportgroup-226 + + + r_network_dvportgroup-657 + l_network_dvportgroup-399 + + + r_network_dvportgroup-648 + l_network_dvportgroup-486 + + + r_network_dvportgroup-603 + l_network_dvportgroup-699 + + + r_network_dvportgroup-462 + l_network_dvportgroup-491 + + + r_network_dvportgroup-348 + l_network_dvportgroup-546 + + + r_network_dvportgroup-494 + l_network_dvportgroup-648 + + + r_network_dvportgroup-697 + l_network_dvportgroup-634 + + + r_network_dvportgroup-686 + l_network_dvportgroup-712 + + + r_network_dvportgroup-17739 + l_network_dvportgroup-25876 + + + r_network_dvportgroup-470 + l_network_dvportgroup-727 + + + r_network_dvportgroup-321 + l_network_dvportgroup-314 + + + r_network_dvportgroup-327 + l_network_dvportgroup-439 + + + r_network_dvportgroup-703 + l_network_dvportgroup-535 + + + r_network_dvportgroup-349 + l_network_dvportgroup-544 + + + r_network_dvportgroup-359 + l_network_dvportgroup-662 + + + r_network_dvportgroup-528 + l_network_dvportgroup-316 + + + r_network_dvportgroup-557 + l_network_dvportgroup-210 + + + r_network_dvportgroup-534 + l_network_dvportgroup-318 + + + r_network_dvportgroup-394 + l_network_dvportgroup-638 + + + r_network_dvportgroup-696 + l_network_dvportgroup-573 + + + r_network_dvportgroup-694 + l_network_dvportgroup-572 + + + r_network_dvportgroup-17742 + l_network_dvportgroup-25879 + + + r_network_dvportgroup-693 + l_network_dvportgroup-571 + + + r_network_dvportgroup-540 + l_network_dvportgroup-587 + + + r_network_dvportgroup-695 + l_network_dvportgroup-292 + + + r_network_dvportgroup-431 + l_network_dvportgroup-481 + + + r_network_dvportgroup-246 + l_network_dvportgroup-461 + + + r_network_dvportgroup-590 + l_network_dvportgroup-564 + + + r_network_dvportgroup-654 + l_network_dvportgroup-583 + + + r_network_dvportgroup-700 + l_network_dvportgroup-231 + + + r_network_dvportgroup-678 + l_network_dvportgroup-496 + + + r_network_dvportgroup-706 + l_network_dvportgroup-530 + + + r_network_dvportgroup-594 + l_network_dvportgroup-562 + + + r_network_dvportgroup-339 + l_network_dvportgroup-674 + + + r_network_dvportgroup-340 + l_network_dvportgroup-676 + + + r_network_dvportgroup-341 + l_network_dvportgroup-668 + + + r_network_dvportgroup-342 + l_network_dvportgroup-671 + + + r_network_dvportgroup-705 + l_network_dvportgroup-304 + + + r_network_dvportgroup-181 + l_network_dvportgroup-397 + + + r_network_dvportgroup-632 + l_network_dvportgroup-286 + + + r_network_dvportgroup-459 + l_network_dvportgroup-672 + + + r_network_dvportgroup-458 + l_network_dvportgroup-683 + + + r_network_dvportgroup-444 + l_network_dvportgroup-421 + + + r_network_dvportgroup-446 + l_network_dvportgroup-423 + + + r_network_dvportgroup-402 + l_network_dvportgroup-422 + + + r_network_dvportgroup-401 + l_network_dvportgroup-438 + + + r_network_dvportgroup-17308 + l_network_dvportgroup-25051 + + + r_network_dvportgroup-17750 + l_network_dvportgroup-25842 + + + r_network_dvportgroup-175 + l_network_dvportgroup-428 + + + r_network_dvportgroup-191 + l_network_dvportgroup-238 + + + r_network_dvportgroup-366 + l_network_dvportgroup-432 + + + r_network_dvportgroup-550 + l_network_dvportgroup-379 + + + r_network_dvportgroup-466 + l_network_dvportgroup-389 + + + r_network_dvportgroup-408 + l_network_dvportgroup-374 + + + r_network_dvportgroup-17725 + l_network_dvportgroup-25862 + + + r_network_dvportgroup-270 + l_network_dvportgroup-395 + + + r_network_dvportgroup-237 + l_network_dvportgroup-257 + + + r_network_dvportgroup-10395 + l_network_dvportgroup-14569 + + + r_network_dvportgroup-3579 + l_network_dvportgroup-4541 + + + r_network_dvportgroup-614 + l_network_dvportgroup-693 + + + r_network_dvportgroup-663 + l_network_dvportgroup-513 + + + r_network_dvportgroup-422 + l_network_dvportgroup-615 + + + r_network_dvportgroup-639 + l_network_dvportgroup-700 + + + r_network_dvportgroup-641 + l_network_dvportgroup-696 + + + r_network_dvportgroup-642 + l_network_dvportgroup-233 + + + r_network_dvportgroup-628 + l_network_dvportgroup-493 + + + r_network_dvportgroup-424 + l_network_dvportgroup-501 + + + r_network_dvportgroup-221 + l_network_dvportgroup-526 + + + r_network_dvportgroup-627 + l_network_dvportgroup-687 + + + r_network_dvportgroup-583 + l_network_dvportgroup-512 + + + r_network_dvportgroup-208 + l_network_dvportgroup-525 + + + r_network_dvportgroup-18846 + l_network_dvportgroup-27876 + + + r_network_dvportgroup-18848 + l_network_dvportgroup-27878 + + + r_network_dvportgroup-19476 + l_network_dvportgroup-29141 + + + r_network_dvportgroup-17364 + l_network_dvportgroup-25160 + + + r_network_dvportgroup-17365 + l_network_dvportgroup-25161 + + + r_network_dvportgroup-183 + l_network_dvportgroup-265 + + + r_network_dvportgroup-17366 + l_network_dvportgroup-25162 + + + r_network_dvportgroup-17367 + l_network_dvportgroup-25163 + + + r_network_dvportgroup-584 + l_network_dvportgroup-372 + + + r_network_dvportgroup-328 + l_network_dvportgroup-360 + + + r_network_dvportgroup-262 + l_network_dvportgroup-236 + + + r_network_dvportgroup-319 + l_network_dvportgroup-427 + + + r_network_dvportgroup-248 + l_network_dvportgroup-456 + + + r_network_dvportgroup-344 + l_network_dvportgroup-453 + + + r_network_dvportgroup-735 + l_network_dvportgroup-775 + + + r_network_dvportgroup-352 + l_network_dvportgroup-449 + + + r_network_dvportgroup-200 + l_network_dvportgroup-475 + + + r_network_dvportgroup-355 + l_network_dvportgroup-656 + + + r_network_dvportgroup-353 + l_network_dvportgroup-659 + + + r_network_dvportgroup-465 + l_network_dvportgroup-551 + + + r_network_dvportgroup-368 + l_network_dvportgroup-287 + + + r_network_dvportgroup-484 + l_network_dvportgroup-215 + + + r_network_dvportgroup-16326 + l_network_dvportgroup-23209 + + + r_network_dvportgroup-449 + l_network_dvportgroup-736 + + + r_network_dvportgroup-376 + l_network_dvportgroup-506 + + + r_network_dvportgroup-323 + l_network_dvportgroup-690 + + + r_network_dvportgroup-19420 + l_network_dvportgroup-29019 + + + r_network_dvportgroup-453 + l_network_dvportgroup-733 + + + r_network_dvportgroup-451 + l_network_dvportgroup-731 + + + r_network_dvportgroup-455 + l_network_dvportgroup-724 + + + r_network_dvportgroup-24535 + l_network_dvportgroup-37206 + + + r_network_dvportgroup-456 + l_network_dvportgroup-624 + + + r_network_dvportgroup-381 + l_network_dvportgroup-457 + + + r_network_dvportgroup-518 + l_network_dvportgroup-473 + + + r_network_dvportgroup-176 + l_network_dvportgroup-711 + + + r_network_dvportgroup-519 + l_network_dvportgroup-474 + + + r_network_dvportgroup-520 + l_network_dvportgroup-467 + + + r_network_dvportgroup-384 + l_network_dvportgroup-643 + + + r_network_dvportgroup-201 + l_network_dvportgroup-464 + + + r_network_dvportgroup-219 + l_network_dvportgroup-222 + + + r_network_dvportgroup-606 + l_network_dvportgroup-514 + + + r_network_dvportgroup-427 + l_network_dvportgroup-276 + + + r_network_dvportgroup-438 + l_network_dvportgroup-738 + + + r_network_dvportgroup-17738 + l_network_dvportgroup-25875 + + + r_network_dvportgroup-13984 + l_network_dvportgroup-19962 + + + r_network_dvportgroup-11483 + l_network_dvportgroup-15847 + + + r_network_dvportgroup-8581 + l_network_dvportgroup-12261 + + + r_network_dvportgroup-3961 + l_network_dvportgroup-5792 + + + r_network_dvportgroup-308 + l_network_dvportgroup-704 + + + r_network_dvportgroup-400 + l_network_dvportgroup-447 + + + r_network_dvportgroup-731 + l_network_dvportgroup-770 + + + r_network_dvportgroup-17732 + l_network_dvportgroup-25869 + + + r_network_dvportgroup-278 + l_network_dvportgroup-347 + + + r_network_dvportgroup-539 + l_network_dvportgroup-358 + + + r_network_dvportgroup-535 + l_network_dvportgroup-273 + + + r_network_dvportgroup-12953 + l_network_dvportgroup-19074 + + + r_network_dvportgroup-386 + l_network_dvportgroup-338 + + + r_network_dvportgroup-22888 + l_network_dvportgroup-35509 + + + r_network_dvportgroup-17727 + l_network_dvportgroup-25864 + + + r_network_dvportgroup-17731 + l_network_dvportgroup-25868 + + + r_network_dvportgroup-23911 + l_network_dvportgroup-36169 + + + r_network_dvportgroup-24253 + l_network_dvportgroup-36736 + + + r_network_dvportgroup-18300 + l_network_dvportgroup-26893 + + + r_network_dvportgroup-19419 + l_network_dvportgroup-29018 + + + r_network_dvportgroup-25459 + l_network_dvportgroup-38900 + + + r_network_dvportgroup-28699 + l_network_dvportgroup-45382 + + + r_network_dvportgroup-22324 + l_network_dvportgroup-34446 + + + r_network_dvportgroup-6975 + l_network_dvportgroup-10007 + + + r_network_dvportgroup-26745 + l_network_dvportgroup-41233 + + + r_network_dvportgroup-28386 + l_network_dvportgroup-44772 + + + r_network_dvportgroup-17755 + l_network_dvportgroup-25847 + + + r_network_dvportgroup-17746 + l_network_dvportgroup-25838 + + + r_network_dvportgroup-17757 + l_network_dvportgroup-25849 + + + r_network_dvportgroup-27526 + l_network_dvportgroup-42818 + + + r_folder_group-v118 + l_folder_group-v793 + + + r_folder_group-v15069 + l_folder_group-v21534 + + + r_folder_group-v14783 + l_folder_group-v21394 + + + r_folder_group-v14740 + l_folder_group-v21386 + + + r_folder_group-v14546 + l_folder_group-v21134 + + + r_folder_group-v14924 + l_folder_group-v21513 + + + r_folder_group-v14559 + l_folder_group-v21147 + + + r_folder_group-v143 + l_folder_group-v818 + + + r_folder_group-v132 + l_folder_group-v807 + + + r_folder_group-v15384 + l_folder_group-v21590 + + + r_folder_group-v121 + l_folder_group-v796 + + + r_folder_group-v14189 + l_folder_group-v20478 + + + r_folder_group-v14162 + l_folder_group-v20449 + + + r_folder_group-v14929 + l_folder_group-v21518 + + + r_folder_group-v14545 + l_folder_group-v21133 + + + r_folder_group-v14700 + l_folder_group-v21233 + + + r_folder_group-v117 + l_folder_group-v792 + + + r_folder_group-v15383 + l_folder_group-v21591 + + + r_folder_group-v131 + l_folder_group-v806 + + + r_folder_group-v122 + l_folder_group-v797 + + + r_folder_group-v14168 + l_folder_group-v20456 + + + r_folder_group-v14219 + l_folder_group-v20497 + + + r_folder_group-v14547 + l_folder_group-v21135 + + + r_folder_group-v14923 + l_folder_group-v21512 + + + r_folder_group-v14205 + l_folder_group-v20488 + + + r_folder_group-v14697 + l_folder_group-v21231 + + + r_folder_group-v14698 + l_folder_group-v21230 + + + r_folder_group-v14706 + l_folder_group-v21229 + + + r_folder_group-v130 + l_folder_group-v805 + + + r_folder_group-v14767 + l_folder_group-v21391 + + + r_folder_group-v14724 + l_folder_group-v21379 + + + r_folder_group-v14557 + l_folder_group-v20501 + + + r_folder_group-v14195 + l_folder_group-v20483 + + + r_folder_group-v14167 + l_folder_group-v20455 + + + r_folder_group-v14926 + l_folder_group-v21515 + + + r_folder_group-v14548 + l_folder_group-v21136 + + + r_folder_group-v14699 + l_folder_group-v21232 + + + r_folder_group-v142 + l_folder_group-v817 + + + r_folder_group-v15385 + l_folder_group-v21589 + + + r_folder_group-v133 + l_folder_group-v808 + + + r_folder_group-v14735 + l_folder_group-v21383 + + + r_folder_group-v14550 + l_folder_group-v20482 + + + r_folder_group-v14556 + l_folder_group-v21144 + + + r_folder_group-v14185 + l_folder_group-v20471 + + + r_folder_group-v14560 + l_folder_group-v21148 + + + r_folder_group-v14161 + l_folder_group-v20448 + + + r_folder_group-v16479 + l_folder_group-v24865 + + + r_folder_group-v14551 + l_folder_group-v21139 + + + r_folder_group-v15386 + l_folder_group-v21588 + + + r_folder_group-v14752 + l_folder_group-v21388 + + + r_folder_group-v14188 + l_folder_group-v20473 + + + r_folder_group-v14555 + l_folder_group-v21143 + + + r_folder_group-v14197 + l_folder_group-v20485 + + + r_folder_group-v14705 + l_folder_group-v21236 + + + r_folder_group-v14739 + l_folder_group-v21385 + + + r_folder_group-v28498 + l_folder_group-v44842 + + + r_folder_group-v14766 + l_folder_group-v21390 + + + r_folder_group-v14703 + l_folder_group-v21227 + + + r_folder_group-v14879 + l_folder_group-v21454 + + + r_folder_group-v14768 + l_folder_group-v21392 + + + r_folder_group-v14848 + l_folder_group-v21446 + + + r_folder_group-v14849 + l_folder_group-v21447 + + + r_folder_group-v14850 + l_folder_group-v21449 + + + r_folder_group-v14782 + l_folder_group-v21393 + + + r_folder_group-v15097 + l_folder_group-v21537 + + + r_folder_group-v14203 + l_folder_group-v20502 + + + r_folder_group-v14221 + l_folder_group-v20499 + + + r_folder_group-v5862 + l_folder_group-v8303 + + + r_folder_group-v14701 + l_folder_group-v21234 + + + r_folder_group-v14788 + l_folder_group-v21396 + + + r_folder_group-v14702 + l_folder_group-v21226 + + + r_folder_group-v14704 + l_folder_group-v21228 + + + r_folder_group-v14942 + l_folder_group-v21531 + + + r_folder_group-v14180 + l_folder_group-v20467 + + + r_folder_group-v14922 + l_folder_group-v21511 + + + r_folder_group-v14202 + l_folder_group-v20487 + + + r_folder_group-v14204 + l_folder_group-v20503 + + + r_folder_group-v14164 + l_folder_group-v20451 + + + r_folder_group-v14927 + l_folder_group-v21516 + + + r_folder_group-v14206 + l_folder_group-v20504 + + + r_folder_group-v14936 + l_folder_group-v21525 + + + r_folder_group-v14177 + l_folder_group-v20464 + + + r_folder_group-v14928 + l_folder_group-v21517 + + + r_folder_group-v14207 + l_folder_group-v20505 + + + r_folder_group-v14930 + l_folder_group-v21519 + + + r_folder_group-v15070 + l_folder_group-v21535 + + + r_folder_group-v15071 + l_folder_group-v21536 + + + r_folder_group-v14208 + l_folder_group-v20489 + + + r_folder_group-v14209 + l_folder_group-v20490 + + + r_folder_group-v14210 + l_folder_group-v20491 + + + r_folder_group-v15382 + l_folder_group-v21592 + + + r_folder_group-v14211 + l_folder_group-v20506 + + + r_folder_group-v15718 + l_folder_group-v21980 + + + r_folder_group-v14212 + l_folder_group-v20492 + + + r_folder_group-v14213 + l_folder_group-v20493 + + + r_folder_group-v14933 + l_folder_group-v21522 + + + r_folder_group-v15381 + l_folder_group-v21593 + + + r_folder_group-v139 + l_folder_group-v814 + + + r_folder_group-v15380 + l_folder_group-v21594 + + + r_folder_group-v15728 + l_folder_group-v21943 + + + r_folder_group-v14935 + l_folder_group-v21524 + + + r_folder_group-v14215 + l_folder_group-v20494 + + + r_folder_group-v14730 + l_folder_group-v21382 + + + r_folder_group-v14190 + l_folder_group-v20475 + + + r_folder_group-v14880 + l_folder_group-v21453 + + + r_folder_group-v15379 + l_folder_group-v21595 + + + r_folder_group-v14881 + l_folder_group-v21452 + + + r_folder_group-v136 + l_folder_group-v811 + + + r_folder_group-v14937 + l_folder_group-v21526 + + + r_folder_group-v14938 + l_folder_group-v21527 + + + r_folder_group-v14217 + l_folder_group-v20496 + + + r_folder_group-v14748 + l_folder_group-v21387 + + + r_folder_group-v14218 + l_folder_group-v20507 + + + r_folder_group-v14939 + l_folder_group-v21528 + + + r_folder_group-v14940 + l_folder_group-v21529 + + + r_folder_group-v14851 + l_folder_group-v21450 + + + r_folder_group-v14220 + l_folder_group-v20498 + + + r_folder_group-v14554 + l_folder_group-v21142 + + + r_folder_group-v134 + l_folder_group-v809 + + + r_folder_group-v15123 + l_folder_group-v21538 + + + r_folder_group-v14941 + l_folder_group-v21530 + + + r_folder_group-v14179 + l_folder_group-v20466 + + + r_folder_group-v14852 + l_folder_group-v21451 + + + r_folder_group-v14160 + l_folder_group-v20447 + + + r_folder_group-v14163 + l_folder_group-v20450 + + + r_folder_group-v15378 + l_folder_group-v21596 + + + r_folder_group-v15717 + l_folder_group-v22071 + + + r_folder_group-v15736 + l_folder_group-v22072 + + + r_folder_group-v15737 + l_folder_group-v21977 + + + r_folder_group-v15738 + l_folder_group-v22091 + + + r_folder_group-v15739 + l_folder_group-v22090 + + + r_folder_group-v24323 + l_folder_group-v36850 + + + r_folder_group-v15700 + l_folder_group-v26945 + + + r_folder_group-v26551 + l_folder_group-v34614 + + + r_folder_group-v21859 + l_folder_group-v22055 + + + r_resource_resgroup-64 + l_resource_resgroup-104 + + + r_resource_resgroup-62 + l_resource_resgroup-102 + + + r_resource_resgroup-72 + l_resource_resgroup-112 + + + r_resource_resgroup-70 + l_resource_resgroup-110 + + + r_resource_resgroup-78 + l_resource_resgroup-116 + + + r_resource_resgroup-68 + l_resource_resgroup-108 + + + r_resource_resgroup-76 + l_resource_resgroup-114 + + + r_resource_resgroup-30885 + l_resource_resgroup-82 + + + r_resource_resgroup-66 + l_resource_resgroup-106 + + + l_network_dvportgroup-466 + l_network_dvportgroup-571 + + + + + + + + _replicationRoot + + BND-BondBanking ABR NoTest + + pg_vm-protection-group-138657742 + true + Abr + itdbisa9000 + l_datastore_datastore-21207 + + l_vm_vm-3558 + true + r_folder_group-v14546 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-627 + + + + + + + BND-Calyx ABR + + pg_vm-protection-group-138657897 + true + Abr + itdbisa9000 + l_datastore_datastore-21208 + + l_vm_vm-3155 + true + r_folder_group-v14545 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-644 + + + + + + + BND-FIS ABR + + pg_vm-protection-group-138658046 + true + Abr + itdbisa9000 + l_datastore_datastore-13939 + + l_vm_vm-3375 + true + r_folder_group-v117 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3557 + true + r_folder_group-v117 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3387 + true + r_folder_group-v117 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-2445 + true + r_folder_group-v117 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3154 + true + r_folder_group-v117 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3544 + true + r_folder_group-v117 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-2825 + true + r_folder_group-v117 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-2880 + true + r_folder_group-v117 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-2836 + true + r_folder_group-v117 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3084 + true + r_folder_group-v117 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3076 + true + r_folder_group-v117 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3295 + true + r_folder_group-v117 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + l_vm_vm-3280 + true + r_folder_group-v117 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-414 + + + + + + + BND-FUNDTECH ABR + + pg_vm-protection-group-138659675 + true + Abr + itdbisa9000 + l_datastore_datastore-13956 + + l_vm_vm-2835 + true + r_folder_group-v122 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-422 + + + + + + l_vm_vm-3089 + true + r_folder_group-v122 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-422 + + + + + + l_vm_vm-2926 + true + r_folder_group-v122 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-422 + + + + + + l_vm_vm-3542 + true + r_folder_group-v122 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-368 + + + + + + + BND-Fiserv ABR + + pg_vm-protection-group-162751055 + true + Abr + itdbisa9000 + l_datastore_datastore-13962 + + l_vm_vm-3553 + true + r_folder_group-v118 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-417 + + + + + + l_vm_vm-3215 + true + r_folder_group-v118 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-417 + + + + + + l_vm_vm-39097 + true + r_folder_group-v118 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-25459 + + + + + + l_vm_vm-39095 + true + r_folder_group-v118 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-25456 + + + + + + + BND-HELMS ABR + + pg_vm-protection-group-138660050 + true + Abr + itdbisa9000 + l_datastore_datastore-21210 + + l_vm_vm-3499 + true + r_folder_group-v14547 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-639 + + + + + + l_vm_vm-3285 + true + r_folder_group-v14547 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-639 + + + + + + l_vm_vm-3502 + true + r_folder_group-v14547 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-639 + + + + + + l_vm_vm-3548 + true + r_folder_group-v14547 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-639 + + + + + + l_vm_vm-3025 + true + r_folder_group-v14547 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-639 + + + + + + + BND-Jreport ABR + + pg_vm-protection-group-138660555 + true + Abr + itdbisa9000 + l_datastore_datastore-21209 + + l_vm_vm-9428 + true + r_folder_group-v14697 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-494 + + + + + + + BND-MFA ABR NoTest + + pg_vm-protection-group-138660836 + true + Abr + itdbisa9000 + l_datastore_datastore-21211 + + l_vm_vm-2448 + true + r_folder_group-v14698 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-550 + + + + + + + BND-MFT VR + pg_vm-protection-group-138683359 + true + Hbr + + l_vm_vm-2760 + true + r_folder_group-v121 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-642 + + + + + + l_vm_vm-3483 + true + r_folder_group-v121 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-641 + + + + + + l_vm_vm-2722 + true + r_folder_group-v121 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-641 + + + + + + l_vm_vm-3549 + true + r_folder_group-v121 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-642 + + + + + + + BND-PitneyBowes ABR + + pg_vm-protection-group-138661194 + true + Abr + itdbisa9000 + l_datastore_datastore-21212 + + l_vm_vm-2462 + true + r_folder_group-v14724 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-462 + + + + + + l_vm_vm-37262 + true + r_folder_group-v14724 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-24535 + + + + + + + BND-SQL ABR + + pg_vm-protection-group-138662345 + true + Abr + itdbisa9000 + l_datastore_datastore-21215 + + l_vm_vm-2958 + true + r_folder_group-v14700 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-686 + + + + + + + BND-Shared-App ABR + + pg_vm-protection-group-138661758 + true + Abr + itdbisa9000 + l_datastore_datastore-21213 + + l_vm_vm-3074 + true + r_folder_group-v14699 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4001 + + r_network_dvportgroup-417 + + + + + + + BND-Shared-App ABR NoTest + + pg_vm-protection-group-138661896 + true + Abr + itdbisa9000 + l_datastore_datastore-21214 + + l_vm_vm-2773 + true + r_folder_group-v14699 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-201 + + + + + + + BND-WebSphere VR + + pg_vm-protection-group-138684035 + true + Hbr + + l_vm_vm-1428 + true + r_folder_group-v14185 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-614 + + + + + + l_vm_vm-1430 + true + r_folder_group-v14185 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-614 + + + + + + l_vm_vm-1429 + true + r_folder_group-v14185 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-614 + + + + + + + CJIS-LERMS ABR + + pg_vm-protection-group-138662563 + true + Abr + itdbisa9000 + l_datastore_datastore-13952 + + l_vm_vm-3142 + true + r_folder_group-v133 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-3540 + true + r_folder_group-v15717 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-663 + + + + + + l_vm_vm-2961 + true + r_folder_group-v15717 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-663 + + + + + + + DES-WebEOC ABR + + pg_vm-protection-group-138665700 + true + Abr + itdbisa9000 + l_datastore_datastore-13947 + + l_vm_vm-3150 + true + r_folder_group-v14548 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-376 + + + + + + + DHS-CDC VR + pg_vm-protection-group-138684535 + true + Hbr + + l_vm_vm-1887 + true + r_folder_group-v14550 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-451 + + + + + + l_vm_vm-41618 + true + r_folder_group-v14550 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-451 + + + + + + + DHS-MMIS-Cognos ABR + + pg_vm-protection-group-138665957 + true + Abr + itdbisa9000 + l_datastore_datastore-13950 + + l_vm_vm-3560 + true + r_folder_group-v14752 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-513 + + + + + + l_vm_vm-3413 + true + r_folder_group-v14752 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-513 + + + + + + + DHS-MMIS-EDIFECS ABR + + pg_vm-protection-group-138666036 + true + Abr + itdbisa9000 + l_datastore_datastore-13951 + l_datastore_datastore-17562 + + l_vm_vm-25166 + true + r_folder_group-v15386 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17364 + + + + + + l_vm_vm-25171 + true + r_folder_group-v15386 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17367 + + + + + + l_vm_vm-25169 + true + r_folder_group-v15386 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17365 + + + + + + l_vm_vm-25167 + true + r_folder_group-v15386 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17364 + + + + + + l_vm_vm-25170 + true + r_folder_group-v15386 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-17366 + + + + + + l_vm_vm-18126 + true + r_folder_group-v15386 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-11483 + + + + + + l_vm_vm-25165 + true + r_folder_group-v15386 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17364 + + + + + + l_vm_vm-25168 + true + r_folder_group-v15386 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17365 + + + + + + l_vm_vm-25164 + true + r_folder_group-v15386 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17364 + + + + + + l_vm_vm-25172 + true + r_folder_group-v15386 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-321 + + + + + + l_vm_vm-25173 + true + r_folder_group-v15386 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-321 + + + + + + + DHS-MMIS-LoadBalancer ABR + + pg_vm-protection-group-138666159 + true + Abr + itdbisa9000 + l_datastore_datastore-13881 + + l_vm_vm-1893 + true + r_folder_group-v14197 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-697 + + + + + + l_vm_vm-1892 + true + r_folder_group-v14197 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-513 + + + + + + + DHS-MMIS-MoveIT ABR + + pg_vm-protection-group-138666238 + true + Abr + itdbisa9000 + l_datastore_datastore-13948 + + l_vm_vm-3555 + true + r_folder_group-v14766 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-608 + + + + + + l_vm_vm-3369 + true + r_folder_group-v14766 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-689 + + + + + + + DHS-MMIS-SIM-SAM ABR + + pg_vm-protection-group-138666317 + true + Abr + itdbisa9000 + l_datastore_datastore-26831 + + l_vm_vm-24860 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24857 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24864 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24862 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24863 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24859 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24861 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24856 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + l_vm_vm-24858 + true + r_folder_group-v16479 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-16326 + + + + + + + DHS-MMIS-Truven-Linux ABR + + pg_vm-protection-group-138666429 + true + Abr + itdbisa9000 + l_datastore_datastore-13878 + l_datastore_datastore-21204 + + l_vm_vm-29089 + true + r_folder_group-v15385 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-19447 + + + + + + l_vm_vm-29088 + true + r_folder_group-v15385 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-19447 + + + + + + l_vm_vm-29085 + true + r_folder_group-v15385 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-19447 + + + + + + l_vm_vm-29526 + true + r_folder_group-v15385 + r_host_host-1126 + r_resource_resgroup-68 + + + 4000 + + r_network_dvportgroup-19478 + + + + + + l_vm_vm-29086 + true + r_folder_group-v15385 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-19447 + + + + + + l_vm_vm-29087 + true + r_folder_group-v15385 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-19447 + + + + + + + DHS-MMIS-UC4 ABR + + pg_vm-protection-group-138666547 + true + Abr + itdbisa9000 + l_datastore_datastore-13874 + + l_vm_vm-1891 + true + r_folder_group-v14768 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-608 + + + + + + l_vm_vm-48924 + true + r_folder_group-v14768 + r_host_host-1706 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-30403 + + + + + + + DHS-MMIS-Xpressions ABR + + pg_vm-protection-group-138666613 + true + Abr + itdbisa9000 + l_datastore_datastore-13949 + + l_vm_vm-2718 + true + r_folder_group-v15736 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-513 + + + + + + l_vm_vm-2976 + true + r_folder_group-v14767 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-608 + + + + + + + DHS-MagiCloud VR + + pg_vm-protection-group-138684771 + true + Hbr + + l_vm_vm-1890 + true + r_folder_group-v14195 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + DHS-Mediclaim ABR + + pg_vm-protection-group-138665883 + true + Abr + itdbisa9000 + l_datastore_datastore-21217 + + l_vm_vm-3230 + true + r_folder_group-v14551 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-278 + + + + + + l_vm_vm-3020 + true + r_folder_group-v14551 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-279 + + + + + + + DHS-MirrorImage VR + pg_vm-protection-group-143332324 + true + Hbr + + l_vm_vm-36793 + true + r_folder_group-v24323 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-24253 + + + + + + + DHS-OpenScan ABR + + pg_vm-protection-group-138666692 + true + Abr + itdbisa9000 + l_datastore_datastore-21216 + + l_vm_vm-3057 + true + r_folder_group-v14739 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-657 + + + + + + + DHS-Orchard ABR + + pg_vm-protection-group-138666762 + true + Abr + itdbisa9000 + l_datastore_datastore-21218 + + l_vm_vm-2780 + true + r_folder_group-v14740 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-520 + + + + + + l_vm_vm-3543 + true + r_folder_group-v14740 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-520 + + + + + + l_vm_vm-2935 + true + r_folder_group-v14740 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-455 + + + + + + + DHS-PitneyBowes VR + pg_vm-protection-group-138684886 + true + Hbr + + l_vm_vm-3234 + true + r_folder_group-v14848 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-35630 + true + r_folder_group-v14848 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-22888 + + + + + + + DHS-Pyxis VR + + pg_vm-protection-group-152826900 + true + Hbr + + l_vm_vm-26890 + true + r_folder_group-v15700 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-18302 + + + + + + l_vm_vm-26891 + true + r_folder_group-v15700 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-18300 + + + + + + + DHS-QMS VR + + pg_vm-protection-group-138685455 + true + Hbr + + l_vm_vm-2460 + true + r_folder_group-v14556 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-308 + + + + + + + DHS-SPACES ABR + + pg_vm-protection-group-138666854 + true + Abr + itdbisa9000 + l_datastore_datastore-13875 + l_datastore_datastore-13894 + l_datastore_datastore-13926 + l_datastore_datastore-13942 + + l_vm_vm-1420 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-700 + + + + + + l_vm_vm-1884 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-590 + + + + + + l_vm_vm-1874 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-623 + + + + + + l_vm_vm-1878 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-616 + + + + + + l_vm_vm-1867 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-706 + + + + + + l_vm_vm-1886 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + l_vm_vm-1863 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-677 + + + + 4001 + + r_network_dvportgroup-677 + + + + 4002 + + r_network_dvportgroup-654 + + + + + + l_vm_vm-1882 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-612 + + + + + + l_vm_vm-1870 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + l_vm_vm-1322 + true + r_folder_group-v15384 + r_host_host-1128 + r_resource_resgroup-66 + + + 4000 + + r_network_dvportgroup-594 + + + + + + l_vm_vm-1421 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-700 + + + + + + l_vm_vm-1321 + true + r_folder_group-v15384 + r_host_host-1128 + r_resource_resgroup-66 + + + 4000 + + r_network_dvportgroup-594 + + + + + + l_vm_vm-1885 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + l_vm_vm-1881 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-703 + + + + + + l_vm_vm-1871 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-703 + + + + + + l_vm_vm-1866 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + l_vm_vm-1424 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-678 + + + + + + l_vm_vm-1883 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-616 + + + + + + l_vm_vm-3372 + true + r_folder_group-v15384 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-606 + + + + + + l_vm_vm-1877 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-623 + + + + + + l_vm_vm-1868 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-623 + + + + + + l_vm_vm-1423 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-678 + + + + + + l_vm_vm-1869 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-706 + + + + + + l_vm_vm-1875 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-679 + + + + + + l_vm_vm-1873 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-612 + + + + + + l_vm_vm-1872 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-590 + + + + + + l_vm_vm-1876 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + l_vm_vm-1864 + true + r_folder_group-v15737 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-653 + + + + 4001 + + r_network_dvportgroup-226 + + + + 4002 + + r_network_dvportgroup-218 + + + + 4003 + + r_network_dvportgroup-226 + + + + + + l_vm_vm-1422 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-678 + + + + + + l_vm_vm-1865 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-677 + + + + 4001 + + r_network_dvportgroup-677 + + + + 4002 + + r_network_dvportgroup-654 + + + + + + l_vm_vm-1425 + true + r_folder_group-v15384 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-678 + + + + + + l_vm_vm-1880 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-679 + + + + + + l_vm_vm-1879 + true + r_folder_group-v15384 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-675 + + + + + + + DHS-SPACES-EDMS VR + pg_vm-protection-group-138725393 + true + Hbr + + l_vm_vm-2560 + true + r_folder_group-v14555 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-449 + + + + + + + DHS-VISION VR + pg_vm-protection-group-138685578 + true + Hbr + + l_vm_vm-2813 + true + r_folder_group-v14849 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-2809 + true + r_folder_group-v14849 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + l_vm_vm-3550 + true + r_folder_group-v14849 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + l_vm_vm-3552 + true + r_folder_group-v14849 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + l_vm_vm-3541 + true + r_folder_group-v14849 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + + DHS-WebSphere VR + pg_vm-protection-group-138686267 + true + Hbr + + l_vm_vm-1380 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1413 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1387 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1407 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1419 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1386 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1414 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1392 + true + r_folder_group-v14188 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + DHS-Workforce-Windows VR + + pg_vm-protection-group-138686986 + true + Hbr + + l_vm_vm-3137 + true + r_folder_group-v14850 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-528 + + + + + + l_vm_vm-2971 + true + r_folder_group-v14850 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-528 + + + + + + + DOH-PRS VR + + pg_vm-protection-group-138687300 + true + Hbr + + l_vm_vm-3143 + true + r_folder_group-v130 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-695 + + + + + + + DOH-Shared-App ABR + + pg_vm-protection-group-138669827 + true + Abr + itdbisa9000 + l_datastore_datastore-21219 + + l_vm_vm-3223 + true + r_folder_group-v14782 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + DOH-USAFoodSafety ABR + + pg_vm-protection-group-138672968 + true + Abr + itdbisa9000 + l_datastore_datastore-21220 + + l_vm_vm-3551 + true + r_folder_group-v14783 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-215 + + + + + + + DOT-STARS VR + + pg_vm-protection-group-138689060 + true + Hbr + + l_vm_vm-2591 + true + r_folder_group-v131 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-438 + + + + + + l_vm_vm-2364 + true + r_folder_group-v131 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-438 + + + + + + l_vm_vm-2422 + true + r_folder_group-v131 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-221 + + + + + + l_vm_vm-2437 + true + r_folder_group-v131 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-438 + + + + + + + DPI-SAAR VR + pg_vm-protection-group-138689659 + true + Hbr + + l_vm_vm-2532 + true + r_folder_group-v132 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-456 + + + + + + l_vm_vm-3366 + true + r_folder_group-v132 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-456 + + + + + + l_vm_vm-49801 + true + r_folder_group-v132 + r_host_host-2171 + r_resource_resgroup-30885 + + 16000 + + 4000 + + r_network_dvportgroup-456 + + + + + + l_vm_vm-49802 + true + r_folder_group-v132 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-456 + + + + + + + ERN-PERSLink VR + + pg_vm-protection-group-138690322 + true + Hbr + + l_vm_vm-2449 + true + r_folder_group-v14559 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-3202 + true + r_folder_group-v14559 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-3009 + true + r_folder_group-v14559 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-3158 + true + r_folder_group-v14559 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-3539 + true + r_folder_group-v14559 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + + + + ERN-PERSLink-Mobile VR + + pg_vm-protection-group-138690883 + true + Hbr + + l_vm_vm-3493 + true + r_folder_group-v15097 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-518 + + + + + + l_vm_vm-2922 + true + r_folder_group-v15097 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-519 + + + + + + + GNF-WebSphere VR + + pg_vm-protection-group-138691197 + true + Hbr + + l_vm_vm-9150 + true + r_folder_group-v14189 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-9148 + true + r_folder_group-v14189 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-446 + + + + + + l_vm_vm-9149 + true + r_folder_group-v14189 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + + ITD-GIS-HUB VR + pg_vm-protection-group-138696447 + true + Hbr + + l_vm_vm-3217 + true + r_folder_group-v14933 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-3471 + true + r_folder_group-v14933 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-534 + + + + + + l_vm_vm-2583 + true + r_folder_group-v14933 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + ITD-Workforce VR + + pg_vm-protection-group-138696038 + true + Hbr + + l_vm_vm-34207 + true + r_folder_group-v15381 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-229 + + + + + + l_vm_vm-12916 + true + r_folder_group-v15381 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-229 + + + + + + l_vm_vm-12915 + true + r_folder_group-v15381 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-229 + + + + + + + Infra-ADFS VR + + pg_vm-protection-group-138691726 + true + Hbr + + l_vm_vm-1950 + true + r_folder_group-v14557 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-628 + + + + + + l_vm_vm-1949 + true + r_folder_group-v14557 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-424 + + + + + + + Infra-ADFS-DirSync VR + pg_vm-protection-group-138692324 + true + Hbr + + l_vm_vm-2592 + true + r_folder_group-v15069 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-628 + + + + + + l_vm_vm-5664 + true + r_folder_group-v15069 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-628 + + + + + + + Infra-Desktop-Encryption VR + + pg_vm-protection-group-138692888 + true + Hbr + + l_vm_vm-2378 + true + r_folder_group-v14922 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Infra-Email-Relay VR + + pg_vm-protection-group-138693089 + true + Hbr + + l_vm_vm-1926 + true + r_folder_group-v14202 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-426 + + + + + + l_vm_vm-1927 + true + r_folder_group-v14202 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-426 + + + + + + + Infra-LDAP-TDS ABR + + pg_vm-protection-group-138673423 + true + Abr + itdbisa9000 + l_datastore_datastore-21200 + + l_vm_vm-1959 + true + r_folder_group-v14203 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-408 + + + + + + + Infra-LicenseMgt-KMS VR + + pg_vm-protection-group-138693278 + true + Hbr + + l_vm_vm-2582 + true + r_folder_group-v14923 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-219 + + + + + + l_vm_vm-2435 + true + r_folder_group-v14924 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Infra-LoadBalancer VR + + pg_vm-protection-group-138694251 + true + Hbr + + l_vm_vm-1960 + true + r_folder_group-v14204 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-499 + + + + 4001 + + r_network_dvportgroup-470 + + + + 4002 + + r_network_dvportgroup-608 + + + + 4003 + + r_network_dvportgroup-435 + + + + + + l_vm_vm-1958 + true + r_folder_group-v14204 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-499 + + + + + + + Infra-LogMGT-Logstash ABR + + pg_vm-protection-group-138676866 + true + Abr + itdbisa9000 + l_datastore_datastore-13886 + + l_vm_vm-2168 + true + r_folder_group-v14208 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Infra-Monitoring-Solarwinds ABR + + pg_vm-protection-group-138677009 + true + Abr + itdbisa9000 + l_datastore_datastore-13918 + + l_vm_vm-1363 + true + r_folder_group-v15738 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-191 + + + + + + + Infra-Monitoring-Solarwinds VR + pg_vm-protection-group-138694707 + true + Hbr + + l_vm_vm-2763 + true + r_folder_group-v15383 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-175 + + + + + + l_vm_vm-2879 + true + r_folder_group-v15383 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-175 + + + + + + l_vm_vm-2721 + true + r_folder_group-v15383 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-175 + + + + + + + Infra-MoveIT VR + pg_vm-protection-group-138695111 + true + Hbr + + l_vm_vm-29308 + true + r_folder_group-v14926 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-19476 + + + + + + l_vm_vm-2469 + true + r_folder_group-v14926 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-5406 + true + r_folder_group-v14926 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-535 + + + + + + l_vm_vm-5405 + true + r_folder_group-v14926 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-3579 + + + + + + + Infra-NetApp VR + pg_vm-protection-group-154782519 + true + Hbr + + l_vm_vm-34044 + true + r_folder_group-v21859 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-6975 + + + + + + + Infra-Networking-Wireless VR + pg_vm-protection-group-138695658 + true + Hbr + + l_vm_vm-2458 + true + r_folder_group-v14927 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-176 + + + + + + + Infra-OneView VR + + pg_vm-protection-group-138696320 + true + Hbr + + l_vm_vm-1957 + true + r_folder_group-v14206 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-390 + + + + + + + Infra-PasswordState ABR + + pg_vm-protection-group-138742322 + true + Abr + itdbisa9000 + l_datastore_datastore-21205 + + l_vm_vm-19963 + true + r_folder_group-v14177 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-13984 + + + + + + l_vm_vm-1350 + true + r_folder_group-v14177 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-540 + + + + + + + Infra-Print VR + pg_vm-protection-group-138696727 + true + Hbr + + l_vm_vm-12730 + true + r_folder_group-v14928 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-12304 + true + r_folder_group-v14928 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-8581 + + + + + + l_vm_vm-2421 + true + r_folder_group-v14928 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-2381 + true + r_folder_group-v14928 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-12305 + true + r_folder_group-v14928 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-8581 + + + + + + l_vm_vm-12393 + true + r_folder_group-v14928 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-8581 + + + + + + + Infra-Proxy VR + pg_vm-protection-group-138697581 + true + Hbr + + l_vm_vm-1951 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-2297 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-542 + + + + 4001 + + r_network_dvportgroup-223 + + + + + + l_vm_vm-1961 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-1953 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-2088 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-542 + + + + 4001 + + r_network_dvportgroup-223 + + + + + + l_vm_vm-1952 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-1956 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-499 + + + + + + l_vm_vm-2298 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-542 + + + + + + l_vm_vm-1955 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-2089 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-542 + + + + 4001 + + r_network_dvportgroup-223 + + + + + + l_vm_vm-1954 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-439 + + + + + + l_vm_vm-2090 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-542 + + + + + + l_vm_vm-45752 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-28699 + + + + + + + Infra-SKLM ABR + + pg_vm-protection-group-138677415 + true + Abr + itdbisa9000 + l_datastore_datastore-21201 + + l_vm_vm-1948 + true + r_folder_group-v14211 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-197 + + + + + + + Infra-Security-AntiVirus-Traps VR + + pg_vm-protection-group-138698683 + true + Hbr + + l_vm_vm-2587 + true + r_folder_group-v14929 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-465 + + + + + + l_vm_vm-2353 + true + r_folder_group-v14929 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-400 + + + + + + + Infra-Security-CertificateAuthority VR + + pg_vm-protection-group-138699198 + true + Hbr + + l_vm_vm-2561 + true + r_folder_group-v14930 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-2465 + true + r_folder_group-v14930 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-2358 + true + r_folder_group-v14930 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Infra-Security-Demisto ABR + + pg_vm-protection-group-152813946 + true + Abr + itdbisa9000 + l_datastore_datastore-40928 + + l_vm_vm-34611 + true + r_folder_group-v26551 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-22324 + + + + + + + Infra-Security-MFA-Azure VR + + pg_vm-protection-group-154783448 + true + Hbr + + l_vm_vm-41453 + true + r_folder_group-v15070 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-401 + + + + + + + Infra-Security-MFA-SafeNet VR + pg_vm-protection-group-138699710 + true + Hbr + + l_vm_vm-2359 + true + r_folder_group-v15071 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-2425 + true + r_folder_group-v15070 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-402 + + + + + + + Infra-Servers-Ansible VR + pg_vm-protection-group-138699956 + true + Hbr + + l_vm_vm-7637 + true + r_folder_group-v14208 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-366 + + + + + + + Infra-Servers-OELR VR + + pg_vm-protection-group-138700551 + true + Hbr + + l_vm_vm-18822 + true + r_folder_group-v14209 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-366 + + + + + + + Infra-Servers-SCCM VR + pg_vm-protection-group-138698833 + true + Hbr + + l_vm_vm-2423 + true + r_folder_group-v15382 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-328 + + + + + + l_vm_vm-1353 + true + r_folder_group-v15739 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-200 + + + + + + + Infra-Servers-Satellite VR + pg_vm-protection-group-138699051 + true + Hbr + + l_vm_vm-1939 + true + r_folder_group-v14210 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-366 + + + + + + l_vm_vm-45630 + true + r_folder_group-v14210 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-366 + + + + + + + Infra-SoftDev-TFS ABR + + pg_vm-protection-group-138677562 + true + Abr + itdbisa9000 + l_datastore_datastore-13960 + + l_vm_vm-2351 + true + r_folder_group-v14788 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Infra-Storage VR + + pg_vm-protection-group-138698558 + true + Hbr + + l_vm_vm-25506 + true + r_folder_group-v15718 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-197 + + + + + + + Infra-UC4 VR + pg_vm-protection-group-138699831 + true + Hbr + + l_vm_vm-15366 + true + r_folder_group-v14212 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-10395 + + + + + + + Infra-Wiki VR + + pg_vm-protection-group-138697452 + true + Hbr + + l_vm_vm-1929 + true + r_folder_group-v14213 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + JSN-UIAA VR + pg_vm-protection-group-138695902 + true + Hbr + + l_vm_vm-2885 + true + r_folder_group-v139 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-381 + + + + + + l_vm_vm-45721 + true + r_folder_group-v139 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-381 + + + + + + + LCN-LEGEND ABR + + pg_vm-protection-group-138677696 + true + Abr + itdbisa9000 + l_datastore_datastore-13877 + l_datastore_datastore-21202 + + l_vm_vm-14471 + true + r_folder_group-v15380 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-3961 + + + + + + l_vm_vm-14473 + true + r_folder_group-v15380 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-3961 + + + + + + l_vm_vm-14474 + true + r_folder_group-v15380 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-3961 + + + + + + l_vm_vm-14472 + true + r_folder_group-v15380 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-3961 + + + + + + l_vm_vm-1900 + true + r_folder_group-v15380 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-648 + + + + + + + LCN-LEGEND-RND ABR + + pg_vm-protection-group-162751766 + true + Abr + itdbisa9000 + l_datastore_datastore-13945 + + l_vm_vm-3776 + true + r_folder_group-v15728 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-327 + + + + + + l_vm_vm-3777 + true + r_folder_group-v15728 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-327 + + + + + + + SOS-BLS VR + + pg_vm-protection-group-138681170 + true + Hbr + + l_vm_vm-8178 + true + r_folder_group-v5862 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-344 + + + + + + l_vm_vm-8177 + true + r_folder_group-v5862 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-352 + + + + + + + SOS-CentralIndexing ABR + + pg_vm-protection-group-138662034 + true + Abr + itdbisa9000 + l_datastore_datastore-13955 + + l_vm_vm-2431 + true + r_folder_group-v142 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-208 + + + + + + l_vm_vm-2355 + true + r_folder_group-v142 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-208 + + + + + + l_vm_vm-2590 + true + r_folder_group-v142 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-583 + + + + + + + Shared-AddressPro VR + + pg_vm-protection-group-138695775 + true + Hbr + + l_vm_vm-2568 + true + r_folder_group-v14935 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-359 + + + + + + + Shared-Apache VR + pg_vm-protection-group-138695448 + true + Hbr + + l_vm_vm-1924 + true + r_folder_group-v14215 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1925 + true + r_folder_group-v14215 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Shared-Cognos VR + pg_vm-protection-group-138695319 + true + Hbr + + l_vm_vm-2382 + true + r_folder_group-v14936 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-608 + + + + + + + Shared-EDMS-Adobe VR + pg_vm-protection-group-138694586 + true + Hbr + + l_vm_vm-10173 + true + r_folder_group-v14190 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-183 + + + + + + + Shared-EDMS-App VR + + pg_vm-protection-group-138694461 + true + Hbr + + l_vm_vm-15849 + true + r_folder_group-v14879 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-557 + + + + + + + Shared-EDMS-FileNet ABR + + pg_vm-protection-group-138679015 + true + Abr + itdbisa9000 + l_datastore_datastore-16821 + l_datastore_datastore-16822 + + l_vm_vm-16866 + true + r_folder_group-v15379 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-355 + + + + + + l_vm_vm-16867 + true + r_folder_group-v15379 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-355 + + + + + + + Shared-EDMS-FileNet VR + pg_vm-protection-group-138693471 + true + Hbr + + l_vm_vm-18226 + true + r_folder_group-v15379 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-248 + + + + + + l_vm_vm-18227 + true + r_folder_group-v15379 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-246 + + + + + + l_vm_vm-1441 + true + r_folder_group-v15379 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-705 + + + + + + l_vm_vm-1447 + true + r_folder_group-v15379 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-705 + + + + + + l_vm_vm-2453 + true + r_folder_group-v15379 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-449 + + + + + + l_vm_vm-18228 + true + r_folder_group-v15379 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-246 + + + + + + l_vm_vm-2356 + true + r_folder_group-v15379 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-449 + + + + + + + Shared-EDMS-eForms VR + pg_vm-protection-group-138694134 + true + Hbr + + l_vm_vm-2347 + true + r_folder_group-v14880 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-353 + + + + + + + Shared-EDMS-iLINX VR + pg_vm-protection-group-138692523 + true + Hbr + + l_vm_vm-2354 + true + r_folder_group-v14881 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-341 + + + + + + l_vm_vm-2579 + true + r_folder_group-v14881 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-340 + + + + + + l_vm_vm-2459 + true + r_folder_group-v14881 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-342 + + + + + + l_vm_vm-2376 + true + r_folder_group-v14881 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-339 + + + + + + l_vm_vm-19436 + true + r_folder_group-v14881 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-12953 + + + + + + + Shared-Email-Exchange ABR + + pg_vm-protection-group-162752054 + true + Abr + itdbisa9000 + l_datastore_datastore-13934 + + l_vm_vm-27928 + true + r_folder_group-v136 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-18846 + + + + + + + Shared-Email-Exchange VR + pg_vm-protection-group-138724862 + true + Hbr + + l_vm_vm-2601 + true + r_folder_group-v136 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-386 + + + + + + + Shared-Email-ListServ VR + pg_vm-protection-group-152827990 + true + Hbr + + l_vm_vm-41444 + true + r_folder_group-v14937 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-18848 + + + + + + + Shared-Email-Lync VR + + pg_vm-protection-group-138691926 + true + Hbr + + l_vm_vm-2588 + true + r_folder_group-v14938 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-349 + + + + 4001 + + r_network_dvportgroup-348 + + + + + + l_vm_vm-2426 + true + r_folder_group-v14938 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-632 + + + + + + + Shared-Email-Pioneer VR + + pg_vm-protection-group-138691605 + true + Hbr + + l_vm_vm-1938 + true + r_folder_group-v14217 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-319 + + + + + + + Shared-Email-Rightfax ABR + + pg_vm-protection-group-162752260 + true + Abr + itdbisa9000 + l_datastore_datastore-21221 + + l_vm_vm-36385 + true + r_folder_group-v14748 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-23911 + + + + + + + Shared-Email-SecureMail VR + + pg_vm-protection-group-138691475 + true + Hbr + + l_vm_vm-1947 + true + r_folder_group-v14207 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-697 + + + + + + + Shared-HEAT VR + + pg_vm-protection-group-138691078 + true + Hbr + + l_vm_vm-2429 + true + r_folder_group-v14939 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Shared-IIS VR + pg_vm-protection-group-152817573 + true + Hbr + + l_vm_vm-2461 + true + r_folder_group-v14940 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-593 + + + + + + + Shared-LotusDomino VR + pg_vm-protection-group-138690051 + true + Hbr + + l_vm_vm-2529 + true + r_folder_group-v14851 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + l_vm_vm-3411 + true + r_folder_group-v14851 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + l_vm_vm-41450 + true + r_folder_group-v14851 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-599 + + + + + + + Shared-MasterDataMgt-MCI VR + pg_vm-protection-group-138689858 + true + Hbr + + l_vm_vm-1945 + true + r_folder_group-v14219 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-608 + + + + + + l_vm_vm-1936 + true + r_folder_group-v14219 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-608 + + + + + + l_vm_vm-43283 + true + r_folder_group-v14219 + r_host_host-1706 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-27526 + + + + + + l_vm_vm-43282 + true + r_folder_group-v14219 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-27526 + + + + + + + Shared-MySQL VR + + pg_vm-protection-group-138689538 + true + Hbr + + l_vm_vm-1931 + true + r_folder_group-v14220 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-499 + + + + + + + Shared-Oracle VR + pg_vm-protection-group-138689417 + true + Hbr + + l_vm_vm-1934 + true + r_folder_group-v14221 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-453 + + + + + + l_vm_vm-45944 + true + r_folder_group-v14221 + r_host_host-1706 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-453 + + + + + + + Shared-PeopleSoft-State ABR + + pg_vm-protection-group-152818450 + true + Abr + itdbisa9000 + l_datastore_datastore-13954 + + l_vm_vm-2350 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-22734 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2384 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2562 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-22730 + true + r_folder_group-v134 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2457 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-22733 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2470 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-2472 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2572 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-2428 + true + r_folder_group-v134 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-22729 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2647 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-2575 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-27452 + true + r_folder_group-v134 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17725 + + + + + + l_vm_vm-2367 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-2440 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-22732 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2430 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2433 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-2569 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-2361 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2366 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-22731 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2436 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-646 + + + + + + l_vm_vm-2383 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-6087 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-2586 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-2566 + true + r_folder_group-v134 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-464 + + + + + + l_vm_vm-40139 + true + r_folder_group-v14554 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-40140 + true + r_folder_group-v14554 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-44701 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17750 + + + + + + l_vm_vm-44704 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17755 + + + + + + l_vm_vm-44700 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17750 + + + + + + l_vm_vm-44702 + true + r_folder_group-v134 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17755 + + + + + + l_vm_vm-44703 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17755 + + + + + + l_vm_vm-44705 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-539 + + + + + + l_vm_vm-44699 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17750 + + + + + + l_vm_vm-45723 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-45722 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-45725 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-45724 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-270 + + + + + + l_vm_vm-49805 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-49804 + true + r_folder_group-v134 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-49803 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-466 + + + + + + l_vm_vm-48381 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17746 + + + + + + l_vm_vm-48797 + true + r_folder_group-v134 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17746 + + + + + + l_vm_vm-48798 + true + r_folder_group-v134 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17746 + + + + + + l_vm_vm-51789 + true + r_folder_group-v134 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17757 + + + + + + + Shared-Peoplesoft-Higher Ed ABR + + pg_vm-protection-group-154764253 + true + Abr + itdbisa9000 + l_datastore_datastore-13953 + + l_vm_vm-29744 + true + r_folder_group-v14554 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17739 + + + + + + l_vm_vm-29743 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17739 + + + + + + l_vm_vm-2385 + true + r_folder_group-v14554 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-629 + + + + + + l_vm_vm-30909 + true + r_folder_group-v14554 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-30911 + true + r_folder_group-v14554 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-275 + + + + + + l_vm_vm-2454 + true + r_folder_group-v14554 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-2456 + true + r_folder_group-v14554 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-25882 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-237 + + + + + + l_vm_vm-30910 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-275 + + + + + + l_vm_vm-35514 + true + r_folder_group-v14554 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17727 + + + + + + l_vm_vm-2571 + true + r_folder_group-v14554 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-34995 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17742 + + + + + + l_vm_vm-35515 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17727 + + + + + + l_vm_vm-35517 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17731 + + + + + + l_vm_vm-35513 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17727 + + + + + + l_vm_vm-27453 + true + r_folder_group-v14554 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17742 + + + + + + l_vm_vm-30908 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-41449 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-237 + + + + + + l_vm_vm-31184 + true + r_folder_group-v14554 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17738 + + + + + + l_vm_vm-30907 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-30912 + true + r_folder_group-v14554 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-275 + + + + + + l_vm_vm-2434 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-34996 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17732 + + + + + + l_vm_vm-2363 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-29742 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17739 + + + + + + l_vm_vm-35518 + true + r_folder_group-v14554 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17731 + + + + + + l_vm_vm-2570 + true + r_folder_group-v14554 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-607 + + + + + + l_vm_vm-35516 + true + r_folder_group-v14554 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-17731 + + + + + + + Shared-Powerschool ABR + + pg_vm-protection-group-138683706 + true + Abr + itdbisa9000 + l_datastore_datastore-34384 + l_datastore_datastore-34385 + l_datastore_datastore-34386 + l_datastore_datastore-34387 + l_datastore_datastore-34388 + l_datastore_datastore-34389 + + l_vm_vm-1210 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1091 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1192 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-902 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1087 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-999 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1126 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1172 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1030 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1187 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1206 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1191 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1066 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1051 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1151 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1050 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1127 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1171 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1010 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1067 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14943 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-901 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14939 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1167 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1110 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14944 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1190 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1026 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1044 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1085 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1168 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1047 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1006 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1005 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1147 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1207 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1104 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1024 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1106 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1188 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1211 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1125 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1186 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1170 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1045 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1004 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1205 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14942 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1025 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1105 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1086 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1059 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1146 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14921 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-903 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1043 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1022 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14941 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1084 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1039 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-997 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1143 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1123 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1119 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1139 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1164 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1002 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1018 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-996 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1144 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1203 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1103 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1003 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1019 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14920 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1124 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1204 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-13550 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1078 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1185 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14936 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1199 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14940 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1082 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1162 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-900 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1117 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1158 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1121 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1183 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1041 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1058 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1000 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1179 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-12921 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1142 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1017 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1218 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1101 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14935 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1001 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1118 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1138 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1099 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1122 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1102 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-998 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1083 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1163 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1042 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1181 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1079 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1177 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1136 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1060 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1159 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1140 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1015 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1120 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1216 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1220 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-907 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1161 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1200 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1116 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1040 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-994 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1100 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1221 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1057 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1198 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1081 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1178 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1182 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1016 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1201 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1020 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1141 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1217 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1114 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1137 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1155 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1135 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1034 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-11242 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14932 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1215 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1180 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1055 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1080 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1160 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1197 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1176 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1115 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14948 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-995 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1012 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1008 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-890 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1213 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-11739 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1129 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1094 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1174 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-991 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1029 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1053 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1113 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1109 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1049 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-904 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1074 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14947 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1033 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1054 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1009 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-20841 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1154 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1175 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1214 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-992 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1111 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14946 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1107 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1092 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1088 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1208 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1189 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1212 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1148 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1072 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1089 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1068 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1152 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1093 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1169 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1193 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1027 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1052 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1048 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-14945 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1128 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1011 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1173 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1069 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1073 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1149 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1153 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-906 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1028 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1032 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1112 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + l_vm_vm-1108 + true + r_folder_group-v15123 + r_host_host-860 + r_resource_resgroup-70 + + + 4000 + + r_network_dvportgroup-731 + + + + + + + Shared-SCCM VR + + pg_vm-protection-group-138687410 + true + Hbr + + l_vm_vm-2539 + true + r_folder_group-v14941 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Shared-SQL ABR + + pg_vm-protection-group-138662975 + true + Abr + itdbisa9000 + l_datastore_datastore-21206 + + l_vm_vm-1362 + true + r_folder_group-v14179 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-262 + + + + + + l_vm_vm-1351 + true + r_folder_group-v14179 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-663 + + + + + + l_vm_vm-1352 + true + r_folder_group-v14179 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-663 + + + + + + l_vm_vm-43967 + true + r_folder_group-v14179 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-262 + + + + + + + Shared-ServiceNow + + pg_vm-protection-group-162812983 + true + Abr + itdbisa9000 + l_datastore_datastore-44914 + + l_vm_vm-44841 + true + r_folder_group-v28498 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-28386 + + + + + + + Shared-SystemZ VR + + pg_vm-protection-group-138687183 + true + Hbr + + l_vm_vm-3224 + true + r_folder_group-v14852 + r_host_host-2336 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-427 + + + + + + + Shared-Video-Pexip VR + pg_vm-protection-group-138686935 + true + Hbr + + l_vm_vm-1281 + true + r_folder_group-v14167 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + + + l_vm_vm-8173 + true + r_folder_group-v14167 + r_host_host-1094 + r_resource_resgroup-76 + + 3000 + + 4000 + + r_network_dvportgroup-735 + + + + + + + Shared-Video-Renovo VR + + pg_vm-protection-group-152827369 + true + Hbr + + l_vm_vm-30640 + true + r_folder_group-v14942 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-19419 + + + + + + l_vm_vm-30639 + true + r_folder_group-v14942 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-19420 + + + + + + + Shared-Video-vBrick VR + pg_vm-protection-group-138686014 + true + Hbr + + l_vm_vm-1288 + true + r_folder_group-v14168 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + + + l_vm_vm-1287 + true + r_folder_group-v14168 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + + + l_vm_vm-33084 + true + r_folder_group-v14168 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + + + l_vm_vm-1273 + true + r_folder_group-v14168 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + 4001 + + r_network_dvportgroup-735 + + + + 4002 + + r_network_dvportgroup-735 + + + + 4003 + + r_network_dvportgroup-735 + + + + + + l_vm_vm-1272 + true + r_folder_group-v14168 + r_host_host-1094 + r_resource_resgroup-76 + + + 4000 + + r_network_dvportgroup-735 + + + + + + + Shared-Voice-Avaya ABR + + pg_vm-protection-group-162752832 + true + Abr + itdbisa9000 + l_datastore_datastore-13867 + + l_vm_vm-9106 + true + r_folder_group-v14160 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-26745 + + + + + + + Shared-Voice-Avaya VR + pg_vm-protection-group-138685010 + true + Hbr + + l_vm_vm-24198 + true + r_folder_group-v14160 + r_host_host-11839 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-713 + + + + 4002 + + r_network_dvportgroup-713 + + + + 4003 + + r_network_dvportgroup-713 + + + + + + l_vm_vm-28218 + true + r_folder_group-v14160 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-713 + + + + + + l_vm_vm-29908 + true + r_folder_group-v14160 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-713 + + + + 4002 + + r_network_dvportgroup-713 + + + + + + l_vm_vm-28217 + true + r_folder_group-v14160 + r_host_host-11839 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-713 + + + + + + l_vm_vm-1487 + true + r_folder_group-v14160 + r_host_host-11839 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + + + l_vm_vm-29906 + true + r_folder_group-v14160 + r_host_host-11839 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-719 + + + + 4002 + + r_network_dvportgroup-713 + + + + + + + Shared-Voice-Avaya-ECAS VR + pg_vm-protection-group-138684652 + true + Hbr + + l_vm_vm-14566 + true + r_folder_group-v14161 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + + + + Shared-Voice-Avaya-IVR VR + pg_vm-protection-group-138684420 + true + Hbr + + l_vm_vm-1500 + true + r_folder_group-v14162 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + + + + Shared-Voice-Avaya-WebConf VR + pg_vm-protection-group-138683242 + true + Hbr + + l_vm_vm-1501 + true + r_folder_group-v14163 + r_host_host-11839 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + + + + Shared-Voice-VoiceMail ABR + + pg_vm-protection-group-138662491 + true + Abr + itdbisa9000 + l_datastore_datastore-21199 + + l_vm_vm-27545 + true + r_folder_group-v14164 + r_host_host-11938 + r_resource_resgroup-62 + + + 4000 + + r_network_dvportgroup-713 + + + + 4001 + + r_network_dvportgroup-713 + + + + + + + Shared-WebSphere VR + pg_vm-protection-group-138681369 + true + Hbr + + l_vm_vm-1390 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1379 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1385 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1394 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1928 + true + r_folder_group-v15378 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1415 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1384 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1411 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1383 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-444 + + + + + + l_vm_vm-1381 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1418 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1410 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1382 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1388 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1393 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1416 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1389 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1417 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-458 + + + + + + l_vm_vm-1409 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1391 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-459 + + + + + + l_vm_vm-1395 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1935 + true + r_folder_group-v15378 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-1412 + true + r_folder_group-v15378 + r_host_host-1168 + r_resource_resgroup-78 + + + 4000 + + r_network_dvportgroup-470 + + + + + + l_vm_vm-41345 + true + r_folder_group-v15378 + r_host_host-1877 + r_resource_resgroup-64 + + + 4000 + + r_network_dvportgroup-446 + + + + + + + Shared-dotNet ABR + + pg_vm-protection-group-138678600 + true + Abr + itdbisa9000 + l_datastore_datastore-13959 + + l_vm_vm-2938 + true + r_folder_group-v14730 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + Shared-dotNet VR + + pg_vm-protection-group-138694982 + true + Hbr + + l_vm_vm-2377 + true + r_folder_group-v14730 + r_host_host-9 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-435 + + + + 4001 + + r_network_dvportgroup-435 + + + + + + + TAX-GenTax VR + pg_vm-protection-group-138680669 + true + Hbr + + l_vm_vm-34997 + true + r_folder_group-v143 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-693 + + + + + + l_vm_vm-45739 + true + r_folder_group-v143 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-694 + + + + + + l_vm_vm-45736 + true + r_folder_group-v143 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-696 + + + + + + l_vm_vm-45741 + true + r_folder_group-v143 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-323 + + + + + + l_vm_vm-45737 + true + r_folder_group-v143 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-696 + + + + + + + WSI-CAPS VR + + pg_vm-protection-group-138680552 + true + Hbr + + l_vm_vm-2815 + true + r_folder_group-v14560 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-431 + + + + + + + WSI-Extranet VR + + pg_vm-protection-group-138680357 + true + Hbr + + l_vm_vm-3546 + true + r_folder_group-v14701 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-484 + + + + + + l_vm_vm-2552 + true + r_folder_group-v14701 + r_host_host-2454 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-484 + + + + + + + WSI-Forms ABR + + pg_vm-protection-group-138661408 + true + Abr + itdbisa9000 + l_datastore_datastore-21222 + + + WSI-ITSM ABR + + pg_vm-protection-group-138661131 + true + Abr + itdbisa9000 + l_datastore_datastore-21223 + + l_vm_vm-3021 + true + r_folder_group-v14703 + r_host_host-2395 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + WSI-Oracle-Reports ABR + + pg_vm-protection-group-138660997 + true + Abr + itdbisa9000 + l_datastore_datastore-21224 + + l_vm_vm-3291 + true + r_folder_group-v14704 + r_host_host-2516 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-584 + + + + + + + WSI-PitneyBowes VR + + pg_vm-protection-group-152828115 + true + Hbr + + l_vm_vm-33988 + true + r_folder_group-v14705 + r_host_host-2171 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-181 + + + + + + + WSI-Reporting VR + pg_vm-protection-group-138679955 + true + Hbr + + l_vm_vm-1366 + true + r_folder_group-v14180 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-394 + + + + + + l_vm_vm-1365 + true + r_folder_group-v14180 + r_host_host-1578 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-392 + + + + + + l_vm_vm-25412 + true + r_folder_group-v14180 + r_host_host-1134 + r_resource_resgroup-72 + + + 4000 + + r_network_dvportgroup-17308 + + + + + + + WSI-Shared-App ABR + + pg_vm-protection-group-138660693 + true + Abr + itdbisa9000 + l_datastore_datastore-21225 + + l_vm_vm-3537 + true + r_folder_group-v14706 + r_host_host-2072 + r_resource_resgroup-30885 + + + 4000 + + r_network_dvportgroup-470 + + + + + + + + +
+
\ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CohesityVMKernelsAndStaticRoutes.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CohesityVMKernelsAndStaticRoutes.ps1 new file mode 100644 index 0000000..f18feea --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CohesityVMKernelsAndStaticRoutes.ps1 @@ -0,0 +1,109 @@ +#$AllVMHosts = Get-Cluster AVAYA*,LINUX*,ODM*,ORACLE*,SQL*,SQL2-DR,TEL*,WAS*,WINDOWS* | Get-VMHost | Sort-object Name + +$VMhostNames = @" +itdbisvm-av05.nd.gov +"@ + +$VMhostNames = ConvertTo-Array -MultiLineString $VMhostNames + +$AllVMHosts = Get-VMHost $VMhostNames + + +$AllVMHosts = Get-Cluster WINDOWS2 | Get-VMHost + +ForEach ($VMHost in $AllVMHosts) { + Clear-DnsClientCache + $VirtualSwitch = $null + $CohesityDNS = $null + $IpAddress = $null + $VMHostDNS = $VMHost.Name + $VirtualSwitch = $VMHost | Get-VirtualSwitch -Name "*Data*" + $PortGroup = $VirtualSwitch | Get-VirtualPortGroup | Where-Object Name -Like "dvPG_3534_10.2.170.0_24*" + $CohesityDNS = $VMHostDNS.split('.')[0] + 'co.nd.gov' + + # does vmhost already have vmkernel in Cohesity range? + If ($VMHost | Get-VMHostNetworkAdapter -VMKernel | Where-Object IP -Like "10.2.170.*") { + Write-Warning "VMKernel already exists on $VMHostDNS" + } + Else { + $IpAddress = (Resolve-DnsName -Name $CohesityDNS).IpAddress + If ($IpAddress) { + New-VMHostNetworkAdapter -VMHost $VMHost ` + -PortGroup $PortGroup ` + -VirtualSwitch $VirtualSwitch ` + -IP $IpAddress ` + -SubnetMask 255.255.255.0 ` + -ManagementTrafficEnabled $true ` + -VMotionEnabled $false ` + -VsanTrafficEnabled $false + } + else { + Write-Error "IpAddress null for $VMHostDNS" + } + } +} + + +<# Create DNS records +$AllVMHosts = @" +itdvmbismgmt01.nd.gov +itdvmbismgmt02.nd.gov +itdvmbisvapp01.nd.gov +itdvmbisvapp02.nd.gov +itdvmbiswas04.nd.gov +itdvmbiswas05.nd.gov +itdvmbisora02.nd.gov +itdvmbisora03.nd.gov +itdvmbissql09.nd.gov +itdvmbissql10.nd.gov +itdvmbissql11.nd.gov +itdvmbiswin07.nd.gov +itdvmbiswin08.nd.gov +itdvmbiswin09.nd.gov +itdvmbiswin10.nd.gov +itdvmbiswin11.nd.gov +itdvmbiswin12.nd.gov +itdvmbiswin13.nd.gov +itdvmbissql07.nd.gov +itdvmbissql08.nd.gov +itdvmmdnmgmt01.nd.gov +itdvmmdnvapp01.nd.gov +itdvmmdnsql07.nd.gov +itdvmmdnsql08.nd.gov +itdvmmdnsql09.nd.gov +itdvmmdnlin05.nd.gov +itdvmmdnora02.nd.gov +itdvmmdnmgmt02.nd.gov +itdvmmdnvapp02.nd.gov +itdvmmdnsql10.nd.gov +itdvmmdnsql11.nd.gov +itdvmmdnsql12.nd.gov +itdvmmdnlin03.nd.gov +itdvmmdnlin04.nd.gov +"@ +$AllVMHosts = ConvertTo-Array -MultiLineString $AllVMHosts +#Get-Cluster WINDOWS2,WAS2,SQL2,SQL2-DR,TEL2,PS2,ORACLE2,ODM2,LINUX2,AVAYA2 | Get-VMHost +ForEach($VMHost in $AllVMhosts){ + $CohesityDNS = $VMHost.split('.')[0] + 'co.nd.gov' + New-ITDIbDNSRecordNextAvailableIP -CIDR 10.2.170.0/24 -Credential $IbCred -Hostname $CohesityDNS + #$CohesityDNS +} +#> + +# static routes +$AllVMHosts = Get-VMHost -Name itdmdnvm-av03.nd.gov +$result = [System.Collections.ArrayList]@() +ForEach ($VMHost in $AllVMHosts) { + $x = $null + $esxcli = Get-EsxCli -VMHost $VMHost -V2 + $params = @{ + network = '10.2.169.128/26' + gateway = '10.2.170.1' + } + + $esxcli.network.ip.route.ipv4.add.Invoke($params) + + $x = $esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'} + $x | Add-Member -Name "Name" -MemberType NoteProperty -Value $VMHost.Name + $null = $result.Add($x) +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CommonTasks.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CommonTasks.ps1 new file mode 100644 index 0000000..2c4a3ec --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/CommonTasks.ps1 @@ -0,0 +1,404 @@ +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#vCenter Credentials + $creds = Get-Credential + Connect-VIServer itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $creds +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#ConvertTo-Array +$VMs=@" +itdtaxtga1.nd.gov +itdtaxpfa1.nd.gov +itdtaxsga1.nd.gov +itdtaxsga2.nd.gov +itdtaxpga1.nd.gov +itdtaxpga2.nd.gov +itdtaxpga3.nd.gov +"@ +$VMs=ConvertTo-Array -MultiLineString $VMs +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Move VM to Datastore + $VMdatastore = 'VMWINDOWS1_143_A9K_R_SHRDPPLSFTST' + Get-VM $VMs | Get-HardDisk + Get-VM $VMs | Move-VM -DiskStorageFormat Thin -Datastore $VMdatastore +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Copy Files to/from Remote Computer + #$fileloc = "C:\Users\delange\State of North Dakota\-Tm-ITD-Virtualization - Documents\VMware\Upgrades\ESXi\6.5.0Update3preGen9\VMware-ESXi-6.5.0-Update3-13932383-HPE-preGen9-650.U3.9.6.8.8-Jun2019.iso" + $fileloc = "C:\users\delange\Downloads\sql.zip" + #$fileloc = "O:\Backups\vp_grandforks\vp_grandforks.bak" + #$fileloc = "C:\temp3\AccelaSchool\*" + #$fileloc = "C:\temp\vp_bis_11252019.bak" + #$fileloc = "C:\ITD\vc-itdvmvc1.nd.gov-2020-01-14--19.33-53492.tgz" + #$fileloc = "D:\Upgrades\VMware\VMware-VCSA-all-6.5.0-14836121.iso" + #$fileloc = "F:\Support Bundles\vc-itdvmvc1.nd.gov-2020-01-07--19.02-29010.tgz" + #$destination = "D:\Upgrades\VMware\" + #$destination = "D:\delange" + #$destination = "C:\users\delange\Downloads\" + #$destination = "C:\inetpub\wwwroot\" + $destination = "D:\ITD\temp\" + #$servers = 'itdvmutil' + $servers = 'itdps-update.nd.gov' + #$servers = 'itdps-images.nd.gov' + #Copy to server + foreach ($server in $servers){ + $s=New-PSSession $server -Credential $creds + Copy-Item $fileloc -ToSession $s -Destination $destination + } + #Copy from server + foreach ($server in $servers){ + $s=New-PSSession $server -Credential $creds + Copy-Item $fileloc -FromSession $s -Destination $destination + } +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Approve New VMs + Compare-ITDVMwareVMtoSharePoint -NewBuilds -OutVariable MatchSP | Format-Table + $MatchSP -Match $false | Sort-Object Name | Format-Table +$VMs=@" +itdohrcdbp1.nd.gov +itdohrcwebp1.nd.gov +"@ +$VMs=ConvertTo-Array -MultiLineString $VMs + Approve-ITDVMwareVMNewBuild -ComputerName $VMs +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Snapshots/Clones + #Get Current Snapshots + Get-VM | Get-Snapshot | Select-Object Name,VM | Sort-Object -Property Name | Format-Table -AutoSize #| clip.exe + #Take Snapshot + $SnapId = 2151..2156 + New-ITDVMwareVMSnapshotTask -id $SnapId -vCenterCredential $creds + #Delete Snapshot from Scripted Task + $SnapId = 2186 + Remove-ITDVMwareVMSnapshot -Id $SnapId -vCenterCredential $creds + #Delete Snapshot taken manually + $VM = 'bnd0704.nd.gov','itdscmt1.nd.gov' + Get-VM -Name $VM | Where-Object -Property PowerState -EQ PoweredOn | Get-Snapshot | Remove-Snapshot -Confirm:$false + #New Clone + $CloneId = 2149 + New-ITDVMwareVMCloneTask -Id $CloneId -vCenterCredential $creds + #Delete Clone + $CloneId = 2117 + Get-VM | Where-Object -Property Name -Like "*$CloneId*" + foreach ($Clone in $CloneId){ + $DeleteClone = Get-VM | Where-Object -Property Name -Like "*$Clone*" + $DeleteClone | Remove-VM -DeleteFromDisk -Confirm:$false + } + #Snap entire vCenter environment at once + Get-VM itdvmpsc1*,itdvmvc1*,itdvmpsc2*,itdvmvc2* | New-Snapshot -Name "Converge External PSC" + Get-VM itdvmpsct1*,itdvmvct1*,itdvmpsct2*,itdvmvct2* | New-Snapshot -Name "PSCT2 Decommissioned" +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Edit VMs + #Add CPU + $VMs = 'itdsql16p1.nd.gov' + $cpu = '4' + Get-VM $VMs + Set-VM $VMs -NumCpu $cpu -Confirm:$false + #Remove CPU + $VMs = 'bnd0557.nd.gov' + $cpu = '1' + Get-VM -Name $VMs | Shutdown-VMGuest -Confirm:$false + #Start-Sleep -Seconds 60 + Get-VM -Name $VMs + Get-VM -Name $VMs | Set-VM -NumCPU $cpu -Confirm:$false + Start-VM $VMs -Confirm:$false + #Increase RAM + $VMs = 'itdcndhf16qps.nd.gov','itdcndhefqps.nd.gov' + $ram = '12' + Get-VM $VMs + Set-VM $VMs -MemoryGB $ram -Confirm:$false + #Remove RAM + $VMs = '' + $ram = '' + Get-VM $VMs | Shutdown-VMGuest -Confirm:$false + Start-Sleep -Seconds 60 + Get-VM -Name $VMs | Set-VM -MemoryGB 16 -Confirm:$false + Start-VM $VMs -Confirm:$false + #Disconnect CDROM + $VMs = 'itdcndstrwt7.nd.gov' + foreach ($VM in $VMs){ + Get-VM $VM | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + #Expand Disks + $VM = 'itdcndstvm04.nd.gov' + Get-VM | Where-Object -Property Name -Like "*$VM*" + Get-VM $VM | Get-HardDisk | Select-Object Name,CapacityGB,Filename + $harddisk = "Hard Disk 2" + $increasedisk = 3 + $datastore = Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk | Get-Datastore + Get-Datastore $datastore | Select Name,FreeSpaceGB,CapacityGB + $newcap = (Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk).CapacityGB + $increasedisk + $newcap + Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk | Set-HardDisk -CapacityGB $newcap -Confirm:$false + #List NumCpu, MemoryGB, Total HardDiskSizeGB + $VMs = 'itd1xaes2','itdbiscmsvr','itdredskyaes','itdwfoaes4' + $datacenter = 'Primary Datacenter' + $harddisk = @{n="HardDiskSizeGB";e={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum}} + foreach ($VM in $VMs){ + Get-Datacenter $datacenter | Get-VM | Where-Object -Property Name -Like "$VM*" | Select-Object -Property Name,NumCpu,MemoryGB,$harddisk + } + foreach ($VM in $VMs){ + Get-VM | Where-Object -Property Name -Like "$VM*" | Get-HardDisk | Select-Object Name,CapacityGB,Filename | Sort-Object Filename -Descending + } +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Port groups + #New distributed port group + $IP = '10.2.160.240/28' <#10.10.10.10/28#> + $VLANid = '3326' <#0001#> + New-ITDVMNetwork -CIDR $IP -VLAN $VLANid + #Remove distributed port group + $portgroup = 'dvPG_' + Get-VDPortgroup | Where-Object -Property Name -EQ $portgroup | Remove-VDPortGroup -Confirm:$false + #Manually add port group + $BismarckVDSwitch = 'dvSwitch3-PDC-AVAYA1-Data' + $MandanVDSwitch = 'dvSwitch3-SDC-AVAYA2-Data' + $PGName = 'dvPG3_2278_165.234.164.0_27' + $VlanId = '2278' + Get-VDSwitch -Name $BismarckVDSwitch | New-VDPortGroup -Name $PGName -NumPorts 1 -VlanId $VlanId + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false + Get-VDSwitch -Name $MandanVDSwitch | New-VDPortGroup -Name $PGName -NumPorts 1 -VLANID $VlanId + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing + Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Delete VMs +#Rename VMs for decommission +$VMs=@" +itdcndstfwp.nd.gov +itdcndstfsowp.nd.gov +itdcndstfwp1.nd.gov +itdcndstfapp1.nd.gov +itdcndstfwp2.nd.gov +itdcndstfapp2.nd.gov +"@ +$VMs=ConvertTo-Array -MultiLineString $VMs + Remove-ITDVMWareVM -ComputerName $VMs | Select-Object -Property Name,PowerState + foreach ($VM in $VMs){ + Get-VM | Where-Object -Property Name -Like "$VM*" | Select-Object -Property Name,PowerState + } +#Delete VM - FINAL DELETE + $deleteVM = foreach ($VM in $VMs){ + Get-VM | Where-Object -Property Name -Like "$VM*delete*" + } + $deleteVM.Name + $deleteVM | Remove-VM -DeleteFromDisk -Confirm:$false +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Replace VMs + $VMs = 'itdexchcasbis2.nd.gov','itdexchcasman2.nd.gov','itdcndhehb.nd.gov','itdcndheclnadd.nd.gov' + foreach ($VM in $VMs){ + $VMold = Get-VM | Where-Object -Property Name -Like "$VM*" | Where-Object -Property PowerState -EQ PoweredOff + $VMnew = Get-VM | Where-Object -Property Name -Like "$VM*new*" + $VMtags = ($VMold | Get-TagAssignment).Tag | Sort-Object -Unique + foreach ($VMtag in $VMtags){ + New-TagAssignment -Entity $VMnew -Tag $VMtag + } + Remove-ITDVMWareVM -ComputerName $VMold.Name + Set-VM -VM $VMnew -Name $VMold -Confirm:$false + } + foreach ($VM in $VMs){ + Get-VM | Where-Object -Property Name -Like "$VM*" | Get-TagAssignment + } +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Datastores +$Datastore = 'VMWINDOWS1_138_A9K_R_BNDFISERV' +#Rescan Host Cluster + Get-Cluster WINDOWS1 | Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs +#Maintenance Mode + $Datastore = 'VMPS1_48_A9K_R','VMPS1_49_A9K_R','VMPS1_50_A9K_R','VMPS1_51_A9K_R','VMPS1_52_A9K_R','VMPS1_53_A9K_R' + Get-Datastore $Datastore | Set-Datastore -MaintenanceMode $true -EvacuateAutomatically + Get-Datastore $Datastore | Set-Datastore -MaintenanceMode $false +#Adding Datastores + $VMhost = 'itdbisvm-sql01.nd.gov' + #Get CanonicalName + Get-ScsiLun -VmHost $VMhost -LunType Disk | Select-Object CanonicalName,CapacityGB | Sort-Object CanonicalName + #Create Datastore + $Datastore = 'VMSQL1_119_A9K_TAX' + $CanonicalName = 'naa.6001738ccce06785000000000018ef24' + New-Datastore -VMHost $VMhost -Name $Datastore -Path $CanonicalName -VMFS -FileSystemVersion 6 +#Removing Datastores + #Datastore Unmap + $Datastores = 'VMLINUX1_248_V5K_SECLOG','VMLINUX1_249_V5K_SECLOG','VMLINUX1_250_V5K_SECLOG','VMLINUX1_251_V5K_SECLOG' + #$Datastores = (Get-DatastoreCluster SQL1_A9K_General | Get-Datastore).Name + foreach ($Datastore in $Datastores){ + Start-ITDVMwareDatastoreUnmap -Datastore $Datastores + } +#Expand Datastore + $Datastore = Get-Datastore 'VMTEL1_124_A9K_VBRICK' + $esxi = Get-View -Id ($Datastore.ExtensionData.Host | Select-Object -Last 1 | Select-Object -ExpandProperty Key) + $DatastoreSystem = Get-View -Id $esxi.ConfigManager.DatastoreSystem + $ExpandOptions = $DatastoreSystem.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) + $DatastoreSystem.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef,$expandOptions.spec) +#Disable Storage I/O Control + $Datastores = 'VMWINDOWS1_90_A9K','VMWINDOWS1_91_A9K','VMWINDOWS1_92_A9K','VMSQL1_57_A9K','VMLINUX1_99_A9K_ELASTIC' + foreach ($Datastore in $Datastores){ + Get-Datastore $Datastore | Set-Datastore -StorageIOControlEnabled $false + } +#Unmount/Detach + #Unmount/Detach + Remove-ITDVmwareDatastoreStep1 -LunId 90 + #Step2 Storage Admin unmaps LUN from Host + #LUN cleanup (after storage unmap, should return empty) + Remove-ITDVMwareDatastoreStep3 -LunId 57 + Remove-ITDVMwareDatastoreStep3 -LunId 90 + Remove-ITDVMwareDatastoreStep3 -LunId 91 + Remove-ITDVMwareDatastoreStep3 -LunId 92 + Remove-ITDVMwareDatastoreStep3 -LunId 99 + + $Id = "_90_" + $Datastores = Get-Datastore | Where-Object Name -Like ("*_" + $Id + "_*") + ForEach ($Datastore in $Datastores) { + $SharePointRecord = $null + + $DatastoreHosts = $Datastore | Get-VMHost + $VMHostCanonicalName = (Get-ScsiLun -VmHost ($DatastoreHosts | Select -First 1) | where-object RuntimeName -Like "*$Id*").CanonicalName + $SharePointRecord = ($SharePointList | Where-Object Title -eq $Datastore.Name) + + If ($SharePointRecord.ExtentName -eq $VMHostCanonicalName) { + Write-Verbose ($Datastore.Name + " *** " + $VMHostCanonicalName + " *** CanonicalName accurate in SharePoint, continuing with unmount") + + try { + Get-Datastore $Datastore #| Unmount-Datastore + $DatastoreHosts | Select-Object -First 1 | Remove-Datastore $Datastore -Confirm:$false -RunASync + $DatastoreRemovalSuccess += $Datastore.Name + } + catch { + $DatastoreRemovalFailure += $Datastore.Name + } + } + else { + Write-Error ($Datastore.Name + " *** " + " *** CanonicalName mismatch with SharePoint Record") + } + } + +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Clusters + #Get cluster that VM resides in + foreach ($VM in $VMs){ + Get-VM $VM | Get-Datastore | Select-Object Name + } + #Get VMs with Resource Reservations + $Cluster = 'TEL1' + $VMs = Get-Cluster $Cluster | Get-VM + $VMs2 = Get-VM | Where-Object {$_.ExtensionData.ResourceConfig.MemoryAllocation.Reservation -ne "0" -or $_.ExtensionData.ResourceConfig.CpuAllocation.Reservation -ne "0"} +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Tags +$VMs=@" +itdintrpmgrp1.nd.gov +"@ +$VMs=ConvertTo-Array -MultiLineString $VMs +#Spectrum Protect for VE + $TagCat = "Backup Management (IBM Spectrum Protect)" + $TagName = "Included" +#RPO + $TagCat = "VR RPO" + $TagName = "ABR" + $TagName = "RPO 0:15" + $TagName = "RPO 0:30" + $TagName = "RPO 1:00" + $TagName = "RPO 2:00" + $TagName = "RPO 4:00" + $TagName = "RPO 8:00" +#VR Datastores + $TagCat = "VR Datastores" + $TagName = "VMAVAYA2_210_A9K_VR" + $TagName = "VMLINUX2_212_A9K_VR" + $TagName = "VMLINUX2_213_A9K_VR" + $TagName = "VMSQL2_218_A9K_VR" + $TagName = "VMTEL2_220_A9K_VR" + $TagName = "VMTEL2_221_A9K_VR" + $TagName = "VMWAS2_222_A9K_VR" + $TagName = "VMWAS2_223_A9K_VR" + $TagName = "VMWINDOWS2_224_A9K_VR" + $TagName = "VMWINDOWS2_225_A9K_VR" + $TagName = "VMWINDOWS2_226_A9K_VR" +#SRM Type + $TagCat = "SRM Type" + $TagName = "SRM Reserved" + $TagName = "SRM Repurposed Suspend" + $TagName = "SRM Repurposed" +#HA Host + $TagCat = "HA" + $TagName = "Dedicated HA Host" +#Assign Tag + foreach ($VM in $VMs){ + $VM = Get-VM $VM | Where-Object -Property PowerState -EQ PoweredOn + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + New-TagAssignment -Entity $VM -Tag (Get-Tag -Server $VIServer -Category $TagCat -Name $TagName) -Server $VIServer + } + foreach ($VMHost in $VMHosts){ + $VMHost = Get-VMHost $VMHost + $VIServer = $VMHost.Uid.split('@')[1].split(':')[0] + New-TagAssignment -Entity $VMHost -Tag (Get-Tag -Server $VIServer -Category $TagCat -Name $TagName) -Server $VIServer + } +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#VMhosts +$VMhosts=@" +itdbisvm-av01.nd.gov +itdbisvm-av02.nd.gov +itdbisvm-av03.nd.gov +itdbisvm-av04.nd.gov +itdbisvm-av05.nd.gov +"@ +$VMhosts=ConvertTo-Array -MultiLineString $VMhosts + #VMhosts by Cluster + $VMhosts = (Get-Cluster | Where-Object -Property Name -EQ WINDOWS1 | Get-VMHost | Sort-Object).Name + #Disable Lockdown Mode + foreach ($VMhost in $VMhosts){ + (Get-VMHost $VMhost | Get-View).ExitLockdownMode() + } + #Enable Lockdown Mode + (Get-VMHost $VMhost | Get-View).EnterLockdownMode() + $VMhosts = Get-Datacenter | Where-Object -Property Uid -Like "*itdvmvc*" | Get-VMHost + (Get-VMHost $Vmhosts | Get-View).EnterLockdownMode() + foreach ($VMhost in $VMhosts){ + (Get-VMHost $VMhost | Get-View).EnterLockdownMode() + } + #Enable SSH services + Get-VMHost $VMhost | Get-VMHostService | Where-Object {$_.Label -eq "SSH"} | Start-VMHostService + Get-VMHost $VMhost | Get-VMHostService | Where-Object {$_.Label -eq "ESXi Shell"} | Start-VMHostService + #Get Lockdown Status for all VMhosts + $VMhosts = Get-Datacenter | Where-Object -Property Uid -Like "*itdvmvc*" | Get-VMHost + $Lockdown = @{N="Lockdown";E={$_.Extensiondata.Config.adminDisabled}} + Get-VMHost $VMhosts | Select-Object Name,$Lockdown + #Disable Alarms + foreach ($VMhost in $VMhosts){ + $disableHost = Get-VMhost $VMhost + $viServer = $disableHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $viServer + $alarmEnabled = $disableHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true){ + $alarmMgr.EnableAlarmActions($disableHost.ExtensionData.MoRef,$false) + } + $disableHost = $null + } + #Enable Alarms + foreach ($VMhost in $VMhosts){ + $enableHost = Get-VMhost $VMhost + $viServer = $enableHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $viServer + $alarmEnabled = $enableHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false){ + $alarmMgr.EnableAlarmActions($enableHost.ExtensionData.MoRef,$true) + } + $enableHost = $null + } +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Disk Space +$VMs=@" +itdcndhhpdb.nd.gov +itdcndhhpdbdr.nd.gov +itdcndhfpdb.nd.gov +itdcndhfpdbdr.nd.gov +"@ +$VMs=ConvertTo-Array -MultiLineString $VMs +$export = 'C:\temp\usedspace.csv' + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export -Append + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Linux1 | Export-Csv $export -Append + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable ODM1 | Export-Csv $export -Append + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable PS1 | Export-Csv $export -Append + Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable WAS1 | Export-Csv $export -Append + Get-VM $WindowsVMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Windows1 | Export-Csv $export -Append +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +$export = "C:\temp2\usedspace.csv" +Export-Csv -Path $export -InputObject $Avaya1 + + +Get-VM $VMs | Select-Object @{n="Cluster"; e={($_ | Get-Cluster).Name}},Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPs.ps1 new file mode 100644 index 0000000..5320080 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPs.ps1 @@ -0,0 +1,97 @@ +Start-Transcript C:\ITDSCRIPT\Logs\GetIPs.txt -Append +#Add-PSSnapin VMware.VimAutomation.Core +Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false + +#Connect +Connect-VIServer itdvmvc1.nd.gov, itdvmvc2.nd.gov + + +##Windows + + +#Output File +$OutFileWin = "c:\inetpub\wwwroot\Win.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileWin | Copy-Item -Destination "D:\Backup\Win\$Date-Win.txt" +Remove-Item $OutFileWin +Start-Sleep -Seconds 5 + + +#Get Powered On VM's +$vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "windows7Guest" ` + -or $_.GuestID -eq "windows7_64Guest" ` + -or $_.GuestID -eq "windows7Server64Guest" ` + -or $_.GuestID -eq "windows8_64Guest" ` + -or $_.GuestID -eq "windows8Server64Guest" ` + -or $_.GuestID -eq "windows9Server64Guest" ` + -or $_.GuestID -eq "winLonghorn64Guest" ` + -or $_.GuestID -eq "winLonghornGuest" ` + -or $_.GuestID -eq "winNetStandardGuest" ` + -or $_.GuestID -eq "winNetEnterpriseGuest" ` + -or $_.GuestID -eq "windows9_64Guest") } +$vmviewwin = $vmwin | Get-View + +$Outputwin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewwin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputWin += $IP + "`n" + } + } + } +} + +#If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline} +If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline } + + + +##Linux + +#Output File +$OutFileLin = "c:\inetpub\wwwroot\Lin.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileLin | Copy-Item -Destination "D:\Backup\Lin\$Date-Lin.txt" +Remove-Item $OutFileLin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "centos6_64Guest" ` + -or $_.GuestID -eq "centos64Guest" ` + -or $_.GuestID -eq "centos7_64Guest" ` + -or $_.GuestID -eq "oracleLinux64Guest" ` + -or $_.GuestID -eq "oracleLinux7_64Guest" ` + -or $_.GuestID -eq "rhel4Guest" ` + -or $_.GuestID -eq "rhel5Guest" ` + -or $_.GuestID -eq "rhel5_64Guest" ` + -or $_.GuestID -eq "rhel6Guest" ` + -or $_.GuestID -eq "rhel6_64Guest" ` + -or $_.GuestID -eq "rhel7_64Guest" ` + -or $_.GuestID -eq "sles11_64Guest" ` + -or $_.GuestID -eq "sles12_64Guest" ` + -or $_.GuestID -eq "ubuntu64Guest") } +$vmviewlin = $vmLin | Get-View + +$OutputLin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewlin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputLin += $IP + "`n" + } + } + } +} + +#If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline} +If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline } + + +Stop-Transcript \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzure.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzure.ps1 new file mode 100644 index 0000000..8044b18 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzure.ps1 @@ -0,0 +1,133 @@ +Start-Transcript C:\itdscript\Logs\GetIPsAzureB.txt -Append +$VerbosePerfrence = "Continue" + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$OutputPath = "C:\inetpub\wwwroot" + +$WindowsIPs = "" +$LinuxIPs = "" +$OutFileWin = $OutputPath + "\AzureWin.txt" +$OutFileLin = $OutputPath + "\AzureLin.txt" +Remove-Item $OutFileWin +Remove-Item $OutFileLin + + +$username="svcitdazurescript@nd.gov" +$usernameg="svcitdazurescript@ndstate.onmicrosoft.com" +#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat +$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString +$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString +$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password +$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg + +Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud -Verbose + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} + +Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) +{ + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} + +If ($WindowsIPs -ne "" -and $WindowsIPs.Length -gt 150) {$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force} +If ($LinuxIPs -ne ""-and $LinuxIPs.Length -gt 150) {$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzureBackup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzureBackup.ps1 new file mode 100644 index 0000000..46002ae --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/GetIPsAzureBackup.ps1 @@ -0,0 +1,89 @@ +start-transcript D:\zm.log -force +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$OutputPath = "C:\inetpub\wwwroot" +$OutputBackupPath = "C:\inetpub\wwwroot\AzureBak\" +$CurrentDateTime = Get-Date -UFormat "%Y%m%d%H%M%S" + + +$BackupIPs = "" +$OutFileBak = $OutputPath + "\AzureBak.txt" +$OutFileBakBackup = $OutputBackupPath + "\AzureBak-$CurrentDateTime.txt" + +Remove-Item $OutFileBak + + +$username="svcitdazurescript@nd.gov" +$usernameg="svcitdazurescript@ndstate.onmicrosoft.com" +#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat +$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString +$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString +$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password +$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg + +Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $BackupVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $BackupIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $BackupIPs += $privateip.privateIPAddress + "`n" + } + } + } + } + +Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) +{ + Set-AzureRMContext -SubscriptionObject $subscription + $BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $BackupVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $BackupIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $BackupIPs += $privateip.privateIPAddress + "`n" + } + } + } +} + +If ($BackupIPs -ne "") { + $BackupIPs | Out-File $OutFileBak -Encoding ASCII -NoNewline -Force + $BackupUPs | Out-File $OutFileBakBackup -Encoding ascii -NoNewline -Force + } diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/HPEILO-Certificates-V2.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/HPEILO-Certificates-V2.ps1 new file mode 100644 index 0000000..ad52e7e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/HPEILO-Certificates-V2.ps1 @@ -0,0 +1,88 @@ +$servers = @" +itdvmbisvdi05lo.nd.gov +itdvmbisvdi06lo.nd.gov +"@ +$servers = ConvertTo-Array -MultiLineString $servers + +# validate DNS is configured +ForEach($server in $servers){ + Resolve-DnsName -Name $server +} + +#ServerHardware.mpHostInfo.mpIpAddresses + +# requires powershell 5.1 as of 2023/02/09 +# Generate CSRs +ForEach ($server in $servers) { + $csr = $Null + $connection = Connect-HPEiLO $server -Credential $iLOCred -DisableCertificateAuthentication + $FQDN = $connection.Hostname + If($FQDN -notlike "itdvm*"){ + $FQDN = ((Get-HPEiLOServerInfo -Connection $connection).ServerName.split('.')[0] + 'lo' + '.nd.gov') + } + $Hostname = $FQDN.split('.')[0] + + Start-HPEiLOCertificateSigningRequest -Connection $connection -State "North Dakota" -Country "US" -City "Bismarck" -Organization "State of North Dakota" -OrganizationalUnit "NDIT" -CommonName $FQDN + + do { + $csr = (Get-HPEiLOCertificateSigningRequest -Connection $connection -ErrorAction SilentlyContinue).CertificateSigningRequest.TrimEnd() + Write-Warning ((Get-Date).tostring() + " pausing for 5 seconds") + Start-Sleep -Seconds 5 + } while ( $csr -eq $null ) + $csr | Set-Content "D:\iLO\CSRs\$FQDN-csr.txt" + Disconnect-HPEiLO -Connection $connection +} + +$CsrList = [System.Collections.ArrayList]@() +ForEach($server in $servers){ + $obj=[PSCustomObject]@{ + 'Server' = $Server + 'CSR' = (Get-Content "D:\iLO\CSRs\$server-csr.txt" -Raw); + } + + $null = $CsrList.Add($obj) +} + +$CsrList | group-object CSR +# If any appear with count not equal to 1, something is broken + + + + +ForEach ($server in $servers){ + Write-Warning "$server csr to clipboard" + Get-Content "D:\iLO\CSRs\$server-csr.txt" | Set-Clipboard + Pause +} + + +ForEach ($server in $servers){ + $certfile = $Null + $cert = $Null + + $connection = Connect-HPEiLO $server -Credential $iloCred -DisableCertificateAuthentication + $FQDN = $connection.Hostname + If($FQDN -notlike "itdvm*"){ + $FQDN = ((Get-HPEiLOServerInfo -Connection $connection).ServerName.split('.')[0] + 'lo' + '.nd.gov') + } + $Hostname = $FQDN.split('.')[0] + $certfile = ($hostname) + "_nd_gov_cert.cer" + $cert = (Get-Content "D:\iLO\Certs\$certfile" -Raw).Replace("`r`n", "`n").Trim() + Import-HPEiLOCertificate -Certificate $cert -Connection $connection -Verbose + Disconnect-HPEiLO -Connection $connection +} + + + +# Refresh server hardware, in powershell 7 +# Connect-OVMgmt +$OVServers = Get-OVServer | Sort-Object ServerName +Foreach($OVServer in $OVServers){ + Write-Warning ("Start " + $OVServer.ServerName) + $OVServer | Update-OVServer -Async + Start-Sleep -Seconds 15 +} + + + +####################### \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/LockdownAndSSH.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/LockdownAndSSH.ps1 new file mode 100644 index 0000000..6a40af6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/LockdownAndSSH.ps1 @@ -0,0 +1,19 @@ +$VMHosts = Get-VMHost + +#SSH Service Status +$SSHServiceStatus = $VMHosts | Get-VMHostService | Where-Object Key -eq "TSM-SSH" | select VMhost,Key,Label,Running + +#Disable SSH +ForEach($item in ($SSHService | Where-Object Running -eq $true)){ + Get-VMHost $item.VMHost | Get-VMHostService | Where-Object Key -eq "TSM-SSH" | Stop-VMHostService +} + + + +#Lockdown status +$LockdownStatus = $VMHosts | Select Name,@{n='LockdownMode';e={$_.ExtensionData.Config.LockdownMode}} + +#Enable Lockdown +ForEach($VMHost in ($LockdownStatus | Where-Object LockdownMode -eq "lockdownDisabled")){ + (Get-VMHost $VMHost.Name | Get-View).EnterLockdownMode() +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/RollingRebootsWithHostProfile.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/RollingRebootsWithHostProfile.ps1 new file mode 100644 index 0000000..2006ac1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/RollingRebootsWithHostProfile.ps1 @@ -0,0 +1,102 @@ +$VMHostNames=@" +itdvmbisps10.nd.gov +itdvmbisps11.nd.gov +itdvmbisps12.nd.gov +itdvmbisps13.nd.gov +itdvmbisps14.nd.gov +itdvmbisps15.nd.gov +itdvmbisps16.nd.gov +itdvmbisps17.nd.gov +itdvmbisps18.nd.gov +"@ + +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames + +<#$VMHostNames | ForEach-Object{ + New-ITDVMwareHostScratchFolder -Site Bismarck $_.split('.')[0] +} +#> +foreach ($VMHostName in $VMHostNames){ + $GetVMHost = Get-VMhost $VMHostName + $VMHostParent = $GetVMHost.Parent + $HostCluster = Get-Cluster $VMHostParent + $NewSpec = New-Object VMware.Vim.ClusterConfigSpec + $NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo + $NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy + $NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true + $HostCluster.ExtensionData.ReconfigureCluster($NewSpec,$true) + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true){ + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef,$false) + } + $VMs = $GetVMHost | Get-VM + #Disconnect CDROM and/or VMtools ISO + foreach ($VM in $VMs){ + $GetVM = Get-VM $VM + $CDDrive = $GetVM | Get-CDDrive + if ($CDDrive | Where-Object {$_.IsoPath -Like "*vmware/isoimages*"}){ + $GetVM | Dismount-Tools + #$CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + elseif ($CDDrive.HostDevice -Like "*drive*"){ + $CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + } + $GetVMHost = $null +} +#Move Powered Off VMs +foreach ($VMHostName in $VMHostNames){ + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostParent = $VMHostDetails.Parent.Name + $VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1 + $VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff" + Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate +} +#Enter Maintenance Mode +Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync +#Monitor +Get-VMHost -Name $VMHostNames | Select-Object Name,ConnectionState,@{Name="VM.count";E={@($_ | Get-VM | Where-Object {$_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm"}).Count}} | sort-object Name + +# shutdown +Get-VMHost -Name $VMHostnames | Stop-VMHost -Confirm:$false + +#status +Get-VMHost -Name $VMHostnames + +# OneView, Update Server Profile from Template +ForEach($VMHostName in $VMHostNames){ + Get-OVServerProfile -Name $VMHostName.split('.')[0] | Update-OVServerProfile -Async -confirm:$false +} + +# Power on +ForEach($VMHostName in $VMHostNames){ + Get-OVServer -ServerName $VMHostName | Start-OVServer -Async +} + +# Verify on and connected +Get-VMHost $VMHostNames + +# attach new host profile +Get-VMHost -Name $VMHostnames | Set-VMHost -Profile "MDN 6.5.0 Synergy General 2203" + +# Apply/Remediate Host Profile (invoke) +Get-VMHost -Name $VMHostnames | Invoke-VMHostProfile -confirm:$false -RunAsync + +# manual check for dvswitch data-user + + +#Exit Maintenance Mode and Enable Alarms +Set-VMHost -VMHost $VMHostNames -State "Connected" -RunAsync +Start-Sleep -Seconds 60 +foreach ($VMHostName in $VMHostNames){ + $GetVMHost = Get-VMhost $VMHostName + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false){ + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef,$true) + } + $GetVMHost = $null +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/ServiceNow-Sandbox.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/ServiceNow-Sandbox.ps1 new file mode 100644 index 0000000..ea25bd8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/ServiceNow-Sandbox.ps1 @@ -0,0 +1,136 @@ +$sctasknum='SCTASK0123474' + +$sctask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $sctasknum -IncludeCustomVariable +$request_itemNum = $sctask.request_item.display_value + +$TimeStampString = Get-Date -UFormat "%Y%m%d%H%M%S" +$CommentsToAdd=@" +$TimeStampString +Added disk +"@ + +Update-ServiceNowRecord -ID $sctask.number -Values @{comments = $CommentsToAdd} # enter comments into sctask +Update-ServiceNowRecord -ID $RitmNum -values @{comments = $CommentsToAdd} +If($CloseTask){ + Update-ServiceNowRecord -Id $sctask.number -Values @{close_notes = $CommentsToAdd; state = "Closed Complete" } +} + + +Update-ServiceNowRecord -ID $sctask.number -Values @{short_description = "VMware VM change for $HostName"} +Update-ServiceNowRecord -ID $sctask.number -Values @{assigned_to = "Donald E. Lange"} +Update-ServiceNowRecord -ID $sctask.number -Values @{assigned_to = $assignTo.name} + + +# full auto cpu/memory +$SCTaskNum = 'SCTASK0123802' + +$SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum +$RitmNum = $SCTask.request_item.display_value + +$RITM = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + +[string]$HostName = ($RITM.CustomVariable | where-object Name -eq server_name).Value +[int]$CPU = ($RITM.CustomVariable | where-object Name -eq Processors).Value +[int]$MemoryGB = ($RITM.CustomVariable | where-object Name -eq MemoryGB).Value +[int]$Disk1 = ($RITM.CustomVariable | where-object Name -eq disk_1_os).Value +[int]$Disk2 = ($RITM.CustomVariable | where-object Name -eq disk_2_swap_disk).Value +[int]$Disk3 = ($RITM.CustomVariable | where-object Name -eq disk_3).Value +[int]$Disk4 = ($RITM.CustomVariable | where-object Name -eq disk_4).Value +[int]$Disk5 = ($RITM.CustomVariable | where-object Name -eq disk_5).Value +[int]$Disk6 = ($RITM.CustomVariable | where-object Name -eq disk_6).Value +[int]$Disk7 = ($RITM.CustomVariable | where-object Name -eq disk_7).Value +[int]$Disk8 = ($RITM.CustomVariable | where-object Name -eq disk_8).Value +[int]$Disk9 = ($RITM.CustomVariable | where-object Name -eq disk_9).Value +[int]$Disk10 = ($RITM.CustomVariable | where-object Name -eq disk_10).Value +[int]$Disk11 = ($RITM.CustomVariable | where-object Name -eq disk_11).Value +[int]$Disk12 = ($RITM.CustomVariable | where-object Name -eq disk_12).Value +[int]$Disk13 = ($RITM.CustomVariable | where-object Name -eq disk_13).Value +[int]$Disk14 = ($RITM.CustomVariable | where-object Name -eq disk_14).Value +[int]$Disk15 = ($RITM.CustomVariable | where-object Name -eq disk_15).Value +[int]$Disk16 = ($RITM.CustomVariable | where-object Name -eq disk_16).Value + +$VM = Get-VM -Name $HostName* | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +Write-Warning -Message ("VM: " + $VM.Name) + +If($CPU -ne 0){ + Write-Verbose -Message ($VM.Name + " attempt increasing CPU to " + $CPU) + try { + $VM | Set-VM -NumCpu $CPU + } + catch { + <#Do this if a terminating exception happens#> + } + +} +If($MemoryGB -ne 0){ + Write-Verbose -Message ($VM.Name + " attempt increasing MemoryGB to " + $CPU) + try { + $VM | Set-VM -MemoryGB $MemoryGB + } + catch{ + + } +} +If($Disk1){ + $HardDisk = $VM | Get-HardDisk -Name "Hard disk 1" + $Datastore = $HardDisk | Get-Datastore + $HardDiskIncreaseGB = $Disk1 - $HardDisk.CapacityGB + $FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB + $FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB + + If ($FreePercentAfter -gt 0.10){ + Write-Warning -Message ("Hard disk 1: Increasing from " + $HardDisk.CapacityGB + "GB to " + $Disk1 + "GB") + #Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4)*100 + "% to " + [math]::round($FreePercentAfter,4)*100 + "%") + Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4) + " to " + [math]::round($FreePercentAfter,4) + "") + $VM | Get-HardDisk -Name "Hard disk 1" | Set-HardDisk -CapacityGB $Disk1 -Confirm:$false + } + Else{ + Write-Error -Message ("Hard disk 1 failed. 20% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter,4) + ".") + } +} +If($Disk2){ + #$VM | Get-HardDisk -Name "Hard disk 2" | Set-HardDisk -CapacityGB $Disk2 +} +If($Disk3){ + #$VM | Get-HardDisk -Name "Hard disk 3" | Set-HardDisk -CapacityGB $Disk3 +} +<# +If($Disk4){ + $VM | Get-HardDisk -Name "Hard disk 4" | Set-HardDisk -CapacityGB $Disk4 +} +If($Disk5){ + $VM | Get-HardDisk -Name "Hard disk 5" | Set-HardDisk -CapacityGB $Disk5 +} +If($Disk6){ + $VM | Get-HardDisk -Name "Hard disk 6" | Set-HardDisk -CapacityGB $Disk6 +} +If($Disk7){ + $VM | Get-HardDisk -Name "Hard disk 7" | Set-HardDisk -CapacityGB $Disk7 +} +If($Disk8){ + $VM | Get-HardDisk -Name "Hard disk 8" | Set-HardDisk -CapacityGB $Disk8 +} +If($Disk9){ + $VM | Get-HardDisk -Name "Hard disk 9" | Set-HardDisk -CapacityGB $Disk9 +} +If($Disk10){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk10 +} +If($Disk11){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk11 +} +If($Disk12){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk12 +} +If($Disk13){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk13 +} +If($Disk14){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk14 +} +If($Disk15){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk15 +} +If($Disk16){ + $VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk16 +}#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Storage Queries.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Storage Queries.ps1 new file mode 100644 index 0000000..4d7b4ec --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Storage Queries.ps1 @@ -0,0 +1,75 @@ +<# +VM level: +VM Name +Storage provisioned per disk +Storage used per disk +Free capacity per disk +Disk Mode ( dependent persistent vs independent persistent ) +Disk Type ( Thick, thin, lazy, eager, etc... ) +Datastore +Replication Technology, if applicable +Datacenter +#> + +$VMStorageList = [System.Collections.ArrayList]@() +$AllVMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +ForEach($VM in $AllVMs){ + $VmObj = [PSCustomObject]@{ + VMName = $VM.Name; + UsedSpaceGB = $VM.UsedSpaceGB; + ProvisionedSpaceGB = $VM.ProvisionedSpaceGB; + Datastores = ($VM | Get-Datastore).Name + DatastoreCluster = ($VM | Get-DatastoreCluster).Name + Replication = switch ( ($VM | Get-TagAssignment -Category 'VR RPO').Tag.Name ){ + {$_ -like "*ABR*"} {"ABR"} + {$_ -like "*:*"} {"VR"} + Default {$false} + } + Datacenter = ($VM | Get-Datacenter).Name + Disks = $VM | Get-HardDisk | Select-Object Name,CapacityGB,@{n='StorageFormat';e={$_.StorageFormat.ToString()}},@{n='Persistence';e={$_.Persistence.ToString()}} + } + $null = $VMStorageList.Add($VmObj) +} + +$VMStorageList | ConvertTo-Json -Depth 5 | Out-File "C:\temp\VMs.json" + + + + +<# +Datastore: +Name +Capacity provisioned +Capacity used +Free capacity +Associated SAN device backing ( LUN Name ) +Space Reclamation rate ( MB/s ) +Datacenter +#> + +$AllDatastores = Get-Datastore +$DatastoreList = [System.Collections.ArrayList]@() +ForEach($Datastore in $AllDatastores){ + Write-Verbose -Message ("Start " + $Datastore.Name) -Verbose + #$Metadata = ($Datastore | Get-ScsiLun | Select-Object -First 1) + + If ( $Datastore.ExtensionData.info.vmfs.UnmapBandwidthSpec.FixedValue){ + # if reclamation rate is enabled at fixed rate, get that rate + $ReclamationRate = ("Enabled at fixed rate: " + $Datastore.ExtensionData.info.vmfs.UnmapBandwidthSpec.FixedValue + " MB/s") + } Else { + $ReclamationRate = "UnmapBandwidthSpec is null. Enabled at Low priority: Deleted or unmapped blocks are reclaimed on the LUN at low priority" + } + + $DatastoreObj = [PSCustomObject]@{ + Name = $Datastore.Name; + CapacityGB = $Datastore.CapacityGB; + UsedSpaceGB = ($Datastore.CapacityGB - $Datastore.FreeSpaceGB); + FreeSpaceGB = $Datastore.FreeSpaceGB; + CanonicalName = ($Datastore | Get-ScsiLun | Select-Object -First 1).CanonicalName; + SpaceReclamationRate = $ReclamationRate; + Datacenter = ($VMHostToUse | Get-Datacenter).Name + } + $null = $DatastoreList.Add($DatastoreObj) +} + +$DatastoreList | ConvertTo-Json -Depth 5 | Out-File "C:\temp\Datastores.json" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDOneViewServerInventoryToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDOneViewServerInventoryToSql.ps1 new file mode 100644 index 0000000..9884e3a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDOneViewServerInventoryToSql.ps1 @@ -0,0 +1,270 @@ +<# +.SYNOPSIS + Daily HPE OneView enclosure and server inventory for PowerBI trending and lifecycle planning. + +.DESCRIPTION + Iterates across all configured HPE OneView appliances, collecting enclosure and server + hardware metadata including compute capacity, power state, and server profile assignment. + Exports timestamped CSVs and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis and + physical hardware purchasing / lifecycle decisions. + + Appliances processed: + itdoneviewp1.nd.gov - Rack servers only (no enclosures) + itdbissyncompp1.nd.gov - Synergy enclosures + servers + itdmdnsyncompp1.nd.gov - Synergy enclosures + servers + +.NOTES + Run the following DDL once to create the destination tables: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Enclosure] + + CREATE TABLE [dbo].[VMware_Trends_Enclosure] ( + [ReportDate] DATETIME2 NOT NULL, + [ApplianceConnection] NVARCHAR(100) NULL, + [EnclosureName] NVARCHAR(255) NOT NULL, + [EnclosureModel] NVARCHAR(255) NULL, + [EnclosureSerialNumber] NVARCHAR(100) NULL, + [Status] NVARCHAR(50) NULL, + [DeviceBayCount] INT NULL + ) + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Server] + + CREATE TABLE [dbo].[VMware_Trends_Server] ( + [ReportDate] DATETIME2 NOT NULL, + [ApplianceConnection] NVARCHAR(100) NULL, + [EnclosureName] NVARCHAR(255) NULL, + [BayNumber] INT NULL, + [ServerHardwareName] NVARCHAR(255) NOT NULL, + [ServerName] NVARCHAR(255) NULL, + [ServerModel] NVARCHAR(255) NULL, + [ServerSerialNumber] NVARCHAR(100) NULL, + [Status] NVARCHAR(50) NULL, + [PowerState] NVARCHAR(50) NULL, + [ServerProfileName] NVARCHAR(255) NULL, + [ProcessorType] NVARCHAR(255) NULL, + [ProcessorCount] INT NULL, + [MemoryGB] DECIMAL(10,2) NULL, + [FormFactor] NVARCHAR(100) NULL + ) + + EnclosureName and BayNumber are NULL for rack-mounted servers not seated in an enclosure. + ServerName is the iLO/DNS hostname populated once a server profile is assigned. +#> +[CmdletBinding()] +param( +) + +#region --- Setup --------------------------------------------------------------- +[string[]] $OVHostnames = @( + 'itdoneviewp1.nd.gov', + 'itdbissyncompp1.nd.gov', + 'itdmdnsyncompp1.nd.gov' +) +[string] $OutputPath = 'C:\temp\OV_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $EnclosureTable = 'VMware_Trends_Enclosure' +[string] $ServerTable = 'VMware_Trends_Server' +[System.Management.Automation.PSCredential] $OVCredential = $PrvCred #$Secret:ndgov_svcitdvmhpe +[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "OVServerInventory_$DateStamp.log") -Append + +#endregion + +#region --- Collect Data From All Appliances ----------------------------------- + +$AllEnclosureResults = [System.Collections.Generic.List[PSCustomObject]]::new() +$AllServerResults = [System.Collections.Generic.List[PSCustomObject]]::new() + +foreach ($OVHostname in $OVHostnames) { + + Write-Verbose "Connecting to HPE OneView: $OVHostname" + Connect-OVMgmt -Hostname $OVHostname -Credential $OVCredential -AuthLoginDomain nd.gov -LoginAcknowledge + + #--- Enclosures ------------------------------------------------------------ + + Write-Verbose "[$OVHostname] Gathering enclosures..." + $Enclosures = Get-OVEnclosure + + # Build URI map for server lookups (only populated if there are enclosures) + $EnclosureUriMap = @{} + foreach ($Enclosure in $Enclosures) { + $EnclosureUriMap[$Enclosure.uri] = $Enclosure.name + + $AllEnclosureResults.Add([PSCustomObject]@{ + ReportDate = $Timestamp + ApplianceConnection = $OVHostname + EnclosureName = $Enclosure.name + EnclosureModel = $Enclosure.model + EnclosureSerialNumber = $Enclosure.serialNumber + Status = $Enclosure.status + DeviceBayCount = ($Enclosure.deviceBays | Measure-Object).Count + }) + } + + #--- Servers --------------------------------------------------------------- + + Write-Verbose "[$OVHostname] Gathering servers..." + $Servers = Get-OVServer | Where-Object { $_.serverName -like 'itdvm*' } + + # Build profile URI map for this appliance + $ProfileUriMap = @{} + Get-OVServerProfile | ForEach-Object { + $ProfileUriMap[$_.uri] = $_.name + } + + Write-Verbose "[$OVHostname] Processing $($Servers.Count) servers..." + + foreach ($Server in $Servers) { + + $EnclosureName = if ($Server.locationUri) { + $EnclosureUriMap[$Server.locationUri] + } else { + $null + } + + $ProfileName = if ($Server.serverProfileUri) { + $ProfileUriMap[$Server.serverProfileUri] + } else { + $null + } + + $MemoryGB = if ($null -ne $Server.memoryMb -and $Server.memoryMb -gt 0) { + [Math]::Round($Server.memoryMb / 1024, 2) + } else { + $null + } + + $AllServerResults.Add([PSCustomObject]@{ + ReportDate = $Timestamp + ApplianceConnection = $OVHostname + EnclosureName = $EnclosureName + BayNumber = if ($null -ne $Server.position) { [int]$Server.position } else { $null } + ServerHardwareName = $Server.name + ServerName = $Server.serverName + ServerModel = $Server.model + ServerSerialNumber = $Server.serialNumber + Status = $Server.status + PowerState = $Server.powerState + ServerProfileName = $ProfileName + ProcessorType = $Server.processorType + ProcessorCount = if ($null -ne $Server.processorCount) { [int]$Server.processorCount } else { $null } + MemoryGB = $MemoryGB + FormFactor = $Server.formFactor + }) + } + + Disconnect-OVMgmt + Write-Verbose "[$OVHostname] Disconnected." +} + +#endregion + +#region --- Export CSVs -------------------------------------------------------- + +$EnclosureCsv = Join-Path $OutputPath "OVEnclosures_$DateStamp.csv" +$ServerCsv = Join-Path $OutputPath "OVServers_$DateStamp.csv" + +$AllEnclosureResults | Export-Csv -Path $EnclosureCsv -NoTypeInformation +$AllServerResults | Export-Csv -Path $ServerCsv -NoTypeInformation + +Write-Verbose "Exported $($AllEnclosureResults.Count) enclosure records to: $EnclosureCsv" +Write-Verbose "Exported $($AllServerResults.Count) server records to: $ServerCsv" + +#endregion + +#region --- SQL Insert: Enclosures --------------------------------------------- + +$EnclosureTable_DT = [System.Data.DataTable]::new() + +$EnclosureColDefs = [ordered]@{ + ReportDate = [datetime] + ApplianceConnection = [string] + EnclosureName = [string] + EnclosureModel = [string] + EnclosureSerialNumber = [string] + Status = [string] + DeviceBayCount = [int] +} + +foreach ($Col in $EnclosureColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$EnclosureTable_DT.Columns.Add($Column) +} + +foreach ($Row in $AllEnclosureResults) { + $DataRow = $EnclosureTable_DT.NewRow() + foreach ($Col in $EnclosureColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$EnclosureTable_DT.Rows.Add($DataRow) +} + +Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' ` + -TableName $EnclosureTable -Credential $SqlCredential -InputData $EnclosureTable_DT + +Write-Verbose "Inserted $($EnclosureTable_DT.Rows.Count) enclosure records into [$Database].[dbo].[$EnclosureTable]" + +#endregion + +#region --- SQL Insert: Servers ------------------------------------------------ + +$ServerTable_DT = [System.Data.DataTable]::new() + +$ServerColDefs = [ordered]@{ + ReportDate = [datetime] + ApplianceConnection = [string] + EnclosureName = [string] + BayNumber = [int] + ServerHardwareName = [string] + ServerName = [string] + ServerModel = [string] + ServerSerialNumber = [string] + Status = [string] + PowerState = [string] + ServerProfileName = [string] + ProcessorType = [string] + ProcessorCount = [int] + MemoryGB = [decimal] + FormFactor = [string] +} + +foreach ($Col in $ServerColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$ServerTable_DT.Columns.Add($Column) +} + +foreach ($Row in $AllServerResults) { + $DataRow = $ServerTable_DT.NewRow() + foreach ($Col in $ServerColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$ServerTable_DT.Rows.Add($DataRow) +} + +Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' ` + -TableName $ServerTable -Credential $SqlCredential -InputData $ServerTable_DT + +Write-Verbose "Inserted $($ServerTable_DT.Rows.Count) server records into [$Database].[dbo].[$ServerTable]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------ +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareClusterMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareClusterMetadataToSql.ps1 new file mode 100644 index 0000000..157a776 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareClusterMetadataToSql.ps1 @@ -0,0 +1,188 @@ +<# +.SYNOPSIS + Daily VMware Cluster metadata report for PowerBI trending and capacity planning. + +.DESCRIPTION + Collects cluster-level metadata from vCenter including DRS/HA configuration, + aggregate compute capacity, and effective resource availability. + Exports a timestamped CSV and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis. + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Cluster] + + CREATE TABLE [dbo].[VMware_Trends_Cluster] ( + [ReportDate] DATETIME2 NOT NULL, + [ClusterName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [DrsEnabled] BIT NOT NULL, + [DrsMode] NVARCHAR(50) NULL, + [HaEnabled] BIT NOT NULL, + [HostCount] INT NULL, + [EffectiveHostCount] INT NULL, + [TotalCpuCores] INT NULL, + [TotalCpuMhz] INT NULL, + [EffectiveCpuMhz] INT NULL, + [TotalMemoryGB] DECIMAL(10,2) NULL, + [EffectiveMemoryGB] DECIMAL(10,2) NULL, + [UsedMemoryGB] DECIMAL(10,2) NULL, + [VMCount] INT NULL + ) + + TotalCpuMhz, EffectiveCpuMhz, TotalMemoryGB, and EffectiveMemoryGB come from + vCenter's cluster summary (real-time aggregate). + UsedMemoryGB is summed from each host's current MemoryUsageGB. + TotalCpuCores is summed from each host's hardware CpuInfo. +#> +[CmdletBinding()] +param( +) + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_Cluster' +[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "ClusterMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build Cluster -> Datacenter Lookup --------------------------------- + +Write-Verbose 'Building cluster-to-datacenter map...' +$ClusterDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-Cluster -Location $_ | ForEach-Object { + $ClusterDatacenterMap[$_.Name] = $DatacenterName + } +} + +#endregion + +#region --- Collect Cluster Data ----------------------------------------------- + +Write-Verbose 'Gathering clusters...' +$AllClusters = Get-Cluster + +Write-Verbose "Processing $($AllClusters.Count) clusters..." + +$Results = foreach ($Cluster in $AllClusters) { + + $Summary = $Cluster.ExtensionData.Summary # reuse for all summary fields + + #--- Aggregate host-level stats that vCenter summary does not expose + $ClusterHosts = Get-VMHost -Location $Cluster + $TotalCpuCores = ($ClusterHosts | ForEach-Object { + $_.ExtensionData.Hardware.CpuInfo.NumCpuCores + } | Measure-Object -Sum).Sum + $UsedMemoryGB = [Math]::Round( + ($ClusterHosts | Measure-Object -Property MemoryUsageGB -Sum).Sum, 2 + ) + $VMCount = ($ClusterHosts | ForEach-Object { + ($_.ExtensionData.Vm | Measure-Object).Count + } | Measure-Object -Sum).Sum + + #--- Capacity from cluster summary + $TotalCpuMhz = $Summary.TotalCpu # MHz + $EffectiveCpuMhz = $Summary.EffectiveCpu # MHz + $TotalMemoryGB = [Math]::Round($Summary.TotalMemory / 1GB, 2) # bytes -> GB + $EffectiveMemGB = [Math]::Round($Summary.EffectiveMemory / 1KB, 2) # MB -> GB + + [PSCustomObject]@{ + ReportDate = $Timestamp + ClusterName = $Cluster.Name + Datacenter = $ClusterDatacenterMap[$Cluster.Name] + DrsEnabled = $Cluster.DrsEnabled + DrsMode = $Cluster.DrsAutomationLevel + HaEnabled = $Cluster.HAEnabled + HostCount = $Summary.NumHosts + EffectiveHostCount = $Summary.NumEffectiveHosts + TotalCpuCores = [int]$TotalCpuCores + TotalCpuMhz = $TotalCpuMhz + EffectiveCpuMhz = $EffectiveCpuMhz + TotalMemoryGB = $TotalMemoryGB + EffectiveMemoryGB = $EffectiveMemGB + UsedMemoryGB = $UsedMemoryGB + VMCount = [int]$VMCount + } +} + +#endregion + +#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "ClusterMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) cluster records to: $OutputFile" + +#endregion + +#region --- SQL Insert --------------------------------------------------------- + +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + ClusterName = [string] + Datacenter = [string] + DrsEnabled = [bool] + DrsMode = [string] + HaEnabled = [bool] + HostCount = [int] + EffectiveHostCount = [int] + TotalCpuCores = [int] + TotalCpuMhz = [int] + EffectiveCpuMhz = [int] + TotalMemoryGB = [decimal] + EffectiveMemoryGB = [decimal] + UsedMemoryGB = [decimal] + VMCount = [int] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) cluster records into [$Database].[dbo].[$Table]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareHostMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareHostMetadataToSql.ps1 new file mode 100644 index 0000000..9afb74f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareHostMetadataToSql.ps1 @@ -0,0 +1,212 @@ +<# +.SYNOPSIS + Daily VMware Host metadata report for PowerBI trending and hardware capacity planning. + +.DESCRIPTION + Collects ESXi host metadata from vCenter including hardware, compute capacity, and + version information. Exports a timestamped CSV and inserts into SQL each run. + Append daily runs to build a historical dataset for PowerBI trend analysis and + physical hardware purchasing / lifecycle decisions. + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_Host] + + CREATE TABLE [dbo].[VMware_Trends_Host] ( + [ReportDate] DATETIME2 NOT NULL, + [HostName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [Cluster] NVARCHAR(100) NULL, + [ConnectionState] NVARCHAR(50) NULL, + [PowerState] NVARCHAR(50) NULL, + [InMaintenanceMode] BIT NOT NULL, + [Model] NVARCHAR(255) NULL, + [ProcessorType] NVARCHAR(255) NULL, + [CpuSockets] INT NULL, + [CoresPerSocket] INT NULL, + [TotalCpuCores] INT NULL, + [CpuMhz] INT NULL, + [TotalCpuMhz] INT NULL, + [MemoryTotalGB] DECIMAL(10,2) NULL, + [MemoryUsageGB] DECIMAL(10,2) NULL, + [VMCount] INT NULL, + [EsxiVersion] NVARCHAR(50) NULL, + [EsxiBuild] NVARCHAR(50) NULL, + [UptimeDays] DECIMAL(10,2) NULL + ) + + MemoryUsageGB reflects real-time memory consumed by running VMs at the time of collection. + UptimeDays will be NULL for hosts that are powered off or disconnected. +#> +[CmdletBinding()] +param( +) + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_Host' +[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1 + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "VMHostMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-host queries) - + +Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...' +$HostClusterMap = @{} +$HostDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostDatacenterMap[$_.Name] = $DatacenterName + } +} + +Get-Cluster | ForEach-Object { + $ClusterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostClusterMap[$_.Name] = $ClusterName + } +} + +#endregion + +#region --- Collect Host Data -------------------------------------------------- + +Write-Verbose 'Gathering hosts...' +$AllHosts = $HostDatacenterMap.Keys | ForEach-Object { Get-VMHost -Name $_ } + +Write-Verbose "Processing $($AllHosts.Count) hosts..." + +$Results = foreach ($VMHost in $AllHosts) { + + $Ext = $VMHost.ExtensionData # single API object -- reuse for all fields + + #--- CPU info from hardware summary + $CpuSockets = $Ext.Hardware.CpuInfo.NumCpuPackages + $TotalCpuCores = $Ext.Hardware.CpuInfo.NumCpuCores + $CoresPerSocket = if ($CpuSockets -gt 0) { [int]($TotalCpuCores / $CpuSockets) } else { $null } + $CpuMhz = $Ext.Hardware.CpuInfo.Hz / 1000000 # Hz -> MHz + $TotalCpuMhz = $Ext.Summary.Hardware.CpuMhz * $TotalCpuCores + + #--- Memory + $MemoryTotalGB = [Math]::Round($VMHost.MemoryTotalGB, 2) + $MemoryUsageGB = [Math]::Round($VMHost.MemoryUsageGB, 2) + + #--- VM count on this host right now + $VMCount = ($Ext.Vm | Measure-Object).Count + + #--- Uptime (null when host is powered off / disconnected) + $UptimeDays = $null + $BootTime = $Ext.Runtime.BootTime + if ($null -ne $BootTime) { + $UptimeDays = [Math]::Round(($RunDate - $BootTime).TotalDays, 2) + } + + [PSCustomObject]@{ + ReportDate = $Timestamp + HostName = $VMHost.Name + Datacenter = $HostDatacenterMap[$VMHost.Name] + Cluster = $HostClusterMap[$VMHost.Name] + ConnectionState = $VMHost.ConnectionState + PowerState = $VMHost.PowerState + InMaintenanceMode = $VMHost.ExtensionData.Runtime.InMaintenanceMode + Model = $Ext.Hardware.SystemInfo.Model + ProcessorType = $VMHost.ProcessorType + CpuSockets = $CpuSockets + CoresPerSocket = $CoresPerSocket + TotalCpuCores = $TotalCpuCores + CpuMhz = [int]$CpuMhz + TotalCpuMhz = $TotalCpuMhz + MemoryTotalGB = $MemoryTotalGB + MemoryUsageGB = $MemoryUsageGB + VMCount = $VMCount + EsxiVersion = $VMHost.Version + EsxiBuild = $VMHost.Build + UptimeDays = $UptimeDays + } +} + +#endregion + +#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "VMHostMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) host records to: $OutputFile" + +#endregion + +#region --- SQL Insert --------------------------------------------------------- + +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + HostName = [string] + Datacenter = [string] + Cluster = [string] + ConnectionState = [string] + PowerState = [string] + InMaintenanceMode = [bool] + Model = [string] + ProcessorType = [string] + CpuSockets = [int] + CoresPerSocket = [int] + TotalCpuCores = [int] + CpuMhz = [int] + TotalCpuMhz = [int] + MemoryTotalGB = [decimal] + MemoryUsageGB = [decimal] + VMCount = [int] + EsxiVersion = [string] + EsxiBuild = [string] + UptimeDays = [decimal] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) host records into [$Database].[dbo].[$Table]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareVMMetadataToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareVMMetadataToSql.ps1 new file mode 100644 index 0000000..9aadc02 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/Sync-ITDVMwareVMMetadataToSql.ps1 @@ -0,0 +1,299 @@ +<# +.SYNOPSIS + Daily VM metadata report for PowerBI trending and hardware capacity planning. + +.DESCRIPTION + Collects VM metadata from vCenter including compute, storage, OS, and VMware Tools + information using only data available within vCenter (no direct guest connections). + Exports a timestamped CSV each run -- append daily runs to build a historical dataset + suitable for PowerBI trend analysis and physical hardware purchasing decisions. + +.PARAMETER vCenterServers + One or more vCenter server hostnames. Defaults to itdvmvc1.nd.gov and itdvmvc2.nd.gov. + +.PARAMETER DatacenterFilter + Wildcard filter applied to datacenter names. Defaults to 'Primary*'. + +.PARAMETER OutputPath + Directory where CSV and log files are written. + Defaults to C:\ITDSCRIPT\Reports\VMMetadata. + +.PARAMETER CredentialPath + Path to a saved PSCredential XML file for unattended/scheduled runs. + Create one interactively with: + Get-Credential | Export-Clixml -Path C:\ITDSCRIPT\Creds\vCenter.xml + When omitted the script prompts for credentials. + +.EXAMPLE + # Interactive run + .\VMware-VMDailyMetadataReport.ps1 + +.EXAMPLE + # Scheduled / unattended run + .\VMware-VMDailyMetadataReport.ps1 -CredentialPath 'C:\ITDSCRIPT\Creds\vCenter.xml' + +.NOTES + Run the following DDL once to create the destination table: + + DROP TABLE IF EXISTS [dbo].[VMware_Trends_VM] + + CREATE TABLE [dbo].[VMware_Trends_VM] ( + [ReportDate] DATETIME2 NOT NULL, + [VMName] NVARCHAR(255) NOT NULL, + [Datacenter] NVARCHAR(100) NULL, + [Cluster] NVARCHAR(100) NULL, + [PowerState] NVARCHAR(50) NULL, + [IsSRMPlaceholder] BIT NOT NULL, + [StoragePlatform] NVARCHAR(100) NULL, + [GuestOS] NVARCHAR(255) NULL, + [vCPUs] INT NULL, + [MemoryGB] DECIMAL(10,2) NULL, + [ProvisionedSpaceGB] DECIMAL(12,2) NULL, + [UsedSpaceGB] DECIMAL(12,2) NULL, + [GuestDiskCapacityGB] DECIMAL(12,2) NULL, + [GuestDiskUsedGB] DECIMAL(12,2) NULL, + [ToolsRunningStatus] NVARCHAR(100) NULL, + [ToolsVersionStatus] NVARCHAR(100) NULL, + [ToolsVersion] NVARCHAR(50) NULL, + [Tag_DRProtection] NVARCHAR(100) NULL, + [Tag_AppName] NVARCHAR(255) NULL, + [Tag_VRDatastores] NVARCHAR(255) NULL, + [Tag_VRRPO] NVARCHAR(100) NULL, + [Tag_DTAP] NVARCHAR(50) NULL, + [Tag_StartupPriority] NVARCHAR(100) NULL, + [Tag_SRMRecoveryType] NVARCHAR(100) NULL, + [Tag_LicensingRestrictions] NVARCHAR(255) NULL + ) + + Guest OS disk capacity / used columns are NULL for powered-off VMs and SRM placeholders. +#> +[CmdletBinding()] +param( +) + +#region --- Setup --------------------------------------------------------------- +[string] $OutputPath = 'C:\temp\VM_Trends\' +[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1' +[string] $Database = 'ITD-Systems-Automation' +[string] $Table = 'VMware_Trends_VM' +[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1 +[System.Management.Automation.PSCredential] $vCenterCredential = $PrvCred + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "VMMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-VM API calls) - + +Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...' +$HostClusterMap = @{} +$HostDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostDatacenterMap[$_.Name] = $DatacenterName + } +} + +Get-Cluster | ForEach-Object { + $ClusterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostClusterMap[$_.Name] = $ClusterName + } +} + +#endregion + +#region --- Collect VM Data ----------------------------------------------------- + +Write-Verbose "Gathering VMs" + +# Include ALL VMs (SRM placeholders flagged via column, not excluded). +# vCLS agent VMs are excluded -- they are vSphere internal and not customer workloads. +$AllVMs = Get-VM | Where-Object { $_.Name -notlike 'vCLS*' } + +#--- Pre-fetch all tag assignments in one API call (avoids per-VM Get-TagAssignment) +Write-Verbose 'Pre-fetching VM tag assignments...' +$TagLookup = @{} +Get-TagAssignment -Entity $AllVMs | ForEach-Object { + $VMId = $_.Entity.Id + $Cat = $_.Tag.Category.Name + $TagName = $_.Tag.Name + if (-not $TagLookup.ContainsKey($VMId)) { $TagLookup[$VMId] = @{} } + if ($TagLookup[$VMId].ContainsKey($Cat)) { + $TagLookup[$VMId][$Cat] += "; $TagName" + } else { + $TagLookup[$VMId][$Cat] = $TagName + } +} + +Write-Verbose "Processing $($AllVMs.Count) VMs..." + +$Results = foreach ($VM in $AllVMs) { + + $Ext = $VM.ExtensionData # single API object -- reuse for all fields + + #--- SRM placeholder detection + $IsSRMPlaceholder = $Ext.Summary.Config.ManagedBy.Type -eq 'placeholderVm' + + #--- Cluster / Datacenter (null-safe: standalone hosts have no cluster entry) + $ClusterName = $HostClusterMap[$VM.VMHost.Name] + $DatacenterName = $HostDatacenterMap[$VM.VMHost.Name] + + #--- Tag assignments (pre-fetched; null when category not assigned to this VM) + $VMTags = if ($TagLookup.ContainsKey($VM.Id)) { $TagLookup[$VM.Id] } else { @{} } + + #--- Storage platform parsed from datastore name convention: VMCLUSTER_LUN_PLATFORM_Desc + # Segment 2 = storage platform identifier (e.g. FS92, A9K). + # Cluster grouping uses the compute Cluster column -- no need to re-derive it here. + $StoragePlatforms = foreach ($DSName in $Ext.Config.DatastoreUrl.Name) { + $Segments = $DSName -split '_' + if ($Segments.Count -ge 3) { $Segments[2] } + } + $StoragePlatform = ($StoragePlatforms | Sort-Object -Unique) -join '; ' + + #--- VMware Tools guest disk info + # Populated only when Tools is running; null otherwise. + $GuestDiskCapacityGB = $null + $GuestDiskUsedGB = $null + if ($Ext.Guest.Disk) { + $TotalCapBytes = ($Ext.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum + $TotalFreeBytes = ($Ext.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum + $GuestDiskCapacityGB = [Math]::Round($TotalCapBytes / 1GB, 2) + $GuestDiskUsedGB = [Math]::Round(($TotalCapBytes - $TotalFreeBytes) / 1GB, 2) + } + + [PSCustomObject]@{ + # --- Identity & grouping + ReportDate = $Timestamp # for PowerBI time-series/trend axis + VMName = $VM.Name + Datacenter = $DatacenterName + Cluster = $ClusterName + PowerState = $VM.PowerState + IsSRMPlaceholder = $IsSRMPlaceholder + StoragePlatform = $StoragePlatform + GuestOS = $Ext.Guest.GuestFullName + + # --- Compute + vCPUs = $VM.NumCpu + MemoryGB = $VM.MemoryGB + + # --- Datastore-level storage + # ProvisionedSpaceGB : maximum the VM could consume (thin disks counted at max size) + # UsedSpaceGB : bytes actually committed on datastores right now + ProvisionedSpaceGB = [Math]::Round($VM.ProvisionedSpaceGB, 2) + UsedSpaceGB = [Math]::Round($VM.UsedSpaceGB, 2) + + # --- Guest OS-level storage (from VMware Tools; null when Tools not running) + # GuestDiskCapacityGB : sum of all volume capacities seen inside the guest + # GuestDiskUsedGB : sum of space consumed across those volumes + GuestDiskCapacityGB = $GuestDiskCapacityGB + GuestDiskUsedGB = $GuestDiskUsedGB + + # --- VMware Tools + # ToolsRunningStatus : guestToolsRunning | guestToolsNotRunning | guestToolsExecutingScripts + # ToolsVersionStatus : guestToolsCurrent | guestToolsNeedUpgrade | guestToolsUnmanaged | guestToolsTooNew + # ToolsVersion : numeric build version string reported by vCenter + ToolsRunningStatus = $Ext.Guest.ToolsRunningStatus + ToolsVersionStatus = $Ext.Guest.ToolsVersionStatus + ToolsVersion = $Ext.Guest.ToolsVersion + + # --- vCenter Tags + Tag_DRProtection = $VMTags['DR Protection'] + Tag_AppName = $VMTags['AppName'] + Tag_VRDatastores = $VMTags['VR Datastores'] + Tag_VRRPO = $VMTags['VR RPO'] + Tag_DTAP = $VMTags['DTAP'] + Tag_StartupPriority = $VMTags['StartupPriority'] + Tag_SRMRecoveryType = $VMTags['SRM Recovery Type'] + Tag_LicensingRestrictions = $VMTags['LicensingRestrictions'] + } +} + +#endregion + +<#region --- Export CSV --------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "VMMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation +Write-Verbose "Exported $($Results.Count) VM records to: $OutputFile" + +#endregion +#> +#region --- SQL Insert --------------------------------------------------------- + +# Build a typed DataTable so Write-SqlTableData knows each column's type +# even when nullable columns contain null values. Type inference from raw +# PSCustomObjects fails when the first row has a null in a numeric column. +$DataTable = [System.Data.DataTable]::new() + +$ColDefs = [ordered]@{ + ReportDate = [datetime] + VMName = [string] + Datacenter = [string] + Cluster = [string] + PowerState = [string] + IsSRMPlaceholder = [bool] + StoragePlatform = [string] + GuestOS = [string] + vCPUs = [int] + MemoryGB = [decimal] + ProvisionedSpaceGB = [decimal] + UsedSpaceGB = [decimal] + GuestDiskCapacityGB = [decimal] + GuestDiskUsedGB = [decimal] + ToolsRunningStatus = [string] + ToolsVersionStatus = [string] + ToolsVersion = [string] + Tag_DRProtection = [string] + Tag_AppName = [string] + Tag_VRDatastores = [string] + Tag_VRRPO = [string] + Tag_DTAP = [string] + Tag_StartupPriority = [string] + Tag_SRMRecoveryType = [string] + Tag_LicensingRestrictions = [string] +} + +foreach ($Col in $ColDefs.GetEnumerator()) { + $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value) + $Column.AllowDBNull = $true + [void]$DataTable.Columns.Add($Column) +} + +foreach ($Row in $Results) { + $DataRow = $DataTable.NewRow() + foreach ($Col in $ColDefs.Keys) { + $Val = $Row.$Col + $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value } + } + [void]$DataTable.Rows.Add($DataRow) +} + +$SqlParams = @{ + ServerInstance = $ServerInstance + DatabaseName = $Database + SchemaName = 'dbo' + TableName = $Table + Credential = $SqlCredential + InputData = $DataTable +} +Write-SqlTableData @SqlParams + +Write-Verbose "Inserted $($DataTable.Rows.Count) VM records into [$Database].[dbo].[$Table]" + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHardening-Pub1075.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHardening-Pub1075.ps1 new file mode 100644 index 0000000..dd46399 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHardening-Pub1075.ps1 @@ -0,0 +1,95 @@ +$VMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + +$SettingName = @( + "tools.setInfo.sizeLimit", + "isolation.device.edit.disable", + "isolation.device.connectable.disable", + "isolation.tools.copy.disable", + "isolation.tools.dnd.disable", + "isolation.tools.setGUIOptions.enable", + "RemoteDisplay.vnc.enabled", + "isolation.tools.paste.disable", + "isolation.tools.diskShrink.disable", + "isolation.tools.diskWiper.disable", + "log.keepOld", + "log.rotateSize" +) + +$Result = [System.Collections.ArrayList]@() +ForEach ($VM in $VMs) { + $GetAdvSetting = Get-AdvancedSetting -Entity $VM -Name $SettingName | select Entity, Name, Value + $obj = [PSCustomObject]@{ + 'Entity' = $VM.Name + "tools.setInfo.sizeLimit" = ($GetAdvSetting | Where-Object Name -EQ 'tools.setInfo.sizeLimit').Value + "isolation.device.edit.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.edit.disable').Value + "isolation.device.connectable.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.connectable.disable').Value + "isolation.tools.copy.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.copy.disable').Value + "isolation.tools.dnd.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.dnd.disable').Value + "isolation.tools.setGUIOptions.enable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.setGUIOptions.enable').Value + "RemoteDisplay.vnc.enabled" = ($GetAdvSetting | Where-Object Name -EQ 'RemoteDisplay.vnc.enabled').Value + "isolation.tools.paste.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.paste.disable').Value + "isolation.tools.diskShrink.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskShrink.disable').Value + "isolation.tools.diskWiper.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskWiper.disable').Value + "log.keepOld" = ($GetAdvSetting | Where-Object Name -EQ 'log.keepOld').Value + "log.rotateSize" = ($GetAdvSetting | Where-Object Name -EQ 'log.rotateSize').Value + } + $Result.Add($obj) +} + +$Result + + +<# Blank Loop +ForEach-Object( ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'' -ne "VALUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name '' -Value TRUE -Confirm:$false -Force:$true +} +#> + +# remediate VMs +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'tools.setInfo.sizeLimit' -ne 1048576 }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'tools.setInfo.sizeLimit' -Value '1048576' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.edit.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.device.edit.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.connectable.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.device.connectable.disable' -Value TRUE -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.copy.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.copy.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.dnd.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.dnd.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.setGUIOptions.enable' -ne "FALSE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.setGUIOptions.enable' -Value 'FALSE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'RemoteDisplay.vnc.enabled' -ne "FALSE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'RemoteDisplay.vnc.enabled' -Value 'FALSE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.paste.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.paste.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskShrink.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.diskShrink.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskWiper.disable' -ne "TRUE" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'isolation.tools.diskWiper.disable' -Value 'TRUE' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.keepOld' -ne "10" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'log.keepOld' -Value '10' -Confirm:$false -Force:$true +} + +ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.rotateSize' -ne "1024000" }).Entity ) { + New-AdvancedSetting -Entity $VM -Name 'log.rotateSize' -Value '1024000' -Confirm:$false -Force:$true +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-Decom.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-Decom.ps1 new file mode 100644 index 0000000..3091d81 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-Decom.ps1 @@ -0,0 +1,56 @@ +$VMHostNames = @" +itdbisvm-gen05.nd.gov +"@ +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames + +# set maintenance and disable alarms +Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync +ForEach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost -Name $VMHostname + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } +} + +#Create Management Switch And Move Adapter +ForEach ($VMHostName in $VMHostNames) { + $vmnic0 = Get-VMHostNetworkAdapter -VMHost $VMHostName -Name "vmnic0" + $vmk0 = Get-VMHost $VMHostName | Get-VMHostNetworkAdapter -Name vmk0 + New-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" + Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" | New-VirtualPortGroup -Name "sPG-MGMT" + $MGMTPG = Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" | Get-VirtualPortGroup -Name "sPG-MGMT" + $MGMTSwitch = Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" + Add-VirtualSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmnic0 -VirtualSwitch $MGMTSwitch -Confirm:$false + Add-VirtualSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmnic0 -VirtualSwitch $MGMTSwitch -VirtualNicPortgroup $MGMTPG -VMHostVirtualNic $vmk0 -Confirm:$false +} + +# remove vmk1 and vmk2 +ForEach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostName | Get-VMHostNetworkAdapter -Name vmk1, vmk2 | Remove-VMHostNetworkAdapter -Confirm:$false +} + +# remove distributed switches +$BackupVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-Backup' +$DataVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-Data-Server' +$vMotionVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-VMotion' +$MgmtVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-MGMT' +ForEach ($VMHostName in $VMHostNames) { + Remove-VDSwitchVMHost -VDSwitch $BackupVDSwitch -VMHost $VMHostName -Confirm:$false + Remove-VDSwitchVMHost -VDSwitch $DataVDSwitch -VMHost $VMHostName -Confirm:$false + Remove-VDSwitchVMHost -VDSwitch $vMotionVDSwitch -VMHost $VMHostName -Confirm:$false + Remove-VDSwitchVMHost -VDSwitch $MgmtVDSwitch -VMHost $VMHostName -Confirm:$false +} +# remove from inventory +ForEach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostName | Remove-VMHost -Confirm:$false +} + +# scrub DNS +# scrub Passwordstate +# scrub Active Directory + +# send storage team request to remove SAN +# send cohesity team request to remove host mappings for backup vmkernels \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-GetWWNs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-GetWWNs.ps1 new file mode 100644 index 0000000..91d7149 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-GetWWNs.ps1 @@ -0,0 +1,15 @@ +$cluster = Get-Cluster + +$hosti = $cluster | Get-VMHost + +$report333 = foreach ($esxi in $hosti) { + + Get-VMHosthba -VMHost $esxi -type FibreChannel | where{$_.STatus -eq 'online'} | + + Select @{N="Host";E={$esxi.Name}}, + + @{N='HBA Node WWN';E={$wwn = "{0:X}" -f $_.NodeWorldWideName; (0..7 | %{$wwn.Substring($_*2,2)}) -join ':'}}, + + @{N='HBA Node WWP';E={$wwp = "{0:X}" -f $_.PortWorldWideName; (0..7 | %{$wwp.Substring($_*2,2)}) -join ':'}} + +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-InitialHostConfiguration.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-InitialHostConfiguration.ps1 new file mode 100644 index 0000000..b672b98 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-InitialHostConfiguration.ps1 @@ -0,0 +1,188 @@ +# VMhost Advanced Options -- see OneNote for documentation +# used to customize the first host of each model per datacenter (host profile will be extracted from this), run the entire code +# also used for customizations that made host profiles angry + +# add to distributed switches first +# pre create the syslog folder for each host +# set the logdir datastore/path value using code below +# if this is not the first host per datacenter, stop after logdir value, host profile SHOULD do the rest + + +$VMHostName = 'itdvmmdntel08.nd.gov' +$VMHost = Get-VMHost -Name $VMHostName +$VMHostCluster = $VMHost | Get-Cluster +$VMHostDatacenter = $VMHost | Get-Datacenter +$EsxCli = Get-EsxCli -VMHost $VMHostName -V2 + +# set advanced settings +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.ESXiShellInteractiveTimeOut | Set-AdvancedSetting -Value 300 -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.ESXiShellTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.DcuiTimeOut | Set-AdvancedSetting -Value 600 -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.solo.enableMob | Set-AdvancedSetting -Value false -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.hostsvc.esxAdminsGroupAutoAdd | Set-AdvancedSetting -Value false -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.hostsvc.esxAdminsGroup | Set-AdvancedSetting -Value "" -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.vimsvc.authValidateInterval | Set-AdvancedSetting -Value 90 -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.certificate.strictX509Compliance | Set-AdvancedSetting -Value true -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logLevel | Set-AdvancedSetting -Value info -Confirm:$false + + +# scratch and syslog +switch ($VMHostDatacenter.Name) { + 'Primary Datacenter' { + $ScratchPath = '/vmfs/volumes/5ef4c13d-6318953e-620e-6cc217314910/scratch' + $LogDirDatastore = 'VMALL1_006_FS92_SCRATCH' + } + 'Secondary Datacenter' { + $ScratchPath = '/vmfs/volumes/5ef4be61-1084f19b-ca0a-6cc217314690/scratch' + $LogDirDatastore = 'VMALL2_007_FS92_SCRATCH' + } + 'DCN Datacenter' { + $ScratchPath = '/vmfs/volumes/6463c3f5-1ffe01b3-3837-e0071befea78/scratch' + $LogDirDatastore = 'VMDCN1_40_V5K' + } + 'Grand Forks Vantis' { + $ScratchPath = '[VMVNTS_040_V5K] syslog/itdvmgfvnts02' + $LogDirDatastore = 'VMVNTS_040_V5K' + } + 'Test Primary Datacenter' { + $ScratchPath = '/vmfs/volumes/5f36e52c-93f96f5c-3c43-6cc2172ed4d0/scratch' + $LogDirDatastore = 'VMTEST_001_FS92_SCRATCH' + } + 'Test Secondary Datacenter' { + $ScratchPath = '/vmfs/volumes/5f36e52c-93f96f5c-3c43-6cc2172ed4d0/scratch' + $LogDirDatastore = 'VMTEST_001_FS92_SCRATCH' + } +} + + +#Get-VMHost -Name $VMHostname | Get-AdvancedSetting -Name ScratchConfig.ConfiguredScratchLocation | Set-AdvancedSetting -Value ($ScratchPath + $VMhostName.split('.')[0]) -Confirm:$false +#Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDir | Set-AdvancedSetting -Value "$LogDirDatastore] syslog" -Confirm:$false +#Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDirUnique | Set-AdvancedSetting -Value true -Confirm:$false + +# 2024 syslog values +$VMHostNameShort = $VMHostName.split('.')[0] +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDir | Set-AdvancedSetting -Value ("[$LogDirDatastore] syslog/$VMHostNameShort") -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDirUnique | Set-AdvancedSetting -Value false -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logHost | Set-AdvancedSetting -Value "tcp://itdvmlogging1.nd.gov:514" -Confirm:$false + +# Pub 1075 requirements, no longer included in host profile +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.PasswordQualityControl" | Set-AdvancedSetting -Value "retry=3 min=disabled,disabled,disabled,disabled,14" -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.AccountLockFailures" | Set-AdvancedSetting -Value "3" -Confirm:$false +Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.PasswordHistory" | Set-AdvancedSetting -Value "24" -Confirm:$false + +# static routes for backups +switch ($VMHostDatacenter.Name) { + 'Primary Datacenter' { $Environment = 'Production-General' } + 'Secondary Datacenter' { $Environment = 'Production-General' } + 'DCN Datacenter' { $Environment = 'Production-DCN' } + 'Grand Forks Vantis' { $Environment = $null } + 'Test Primary Datacenter' { $Environment = 'Sandbox' } + 'Test Secondary Datacenter' { $Environment = 'Sandbox' } +} + +switch ($Environment) { + 'Production-General' { + $vmk0IP = (Resolve-DnsName -Name $VMHostName).IPAddress + $vmk1IP = '10.8.142.' + $vmk0IP.split('.')[3] + $vmk2IP = '10.2.170.' + $vmk0IP.split('.')[3] + } +} + +switch ($VMHostDatacenter.Name) { + 'Primary Datacenter' { + Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-PDC-VMotion' -PortGroup 'dvPG_PDC_VMotion' -IP $vmk1IP -SubnetMask 255.255.254.0 -VMotionEnabled $true + Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-PDC-Backup' -PortGroup 'dvPG_3534_10.2.170.0_24' -IP $vmk2IP -SubnetMask 255.255.255.0 + } + 'Secondary Datacenter' { + Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-SDC-VMotion' -PortGroup 'dvPG_SDC_VMotion' -IP $vmk1IP -SubnetMask 255.255.254.0 -VMotionEnabled $true + Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-SDC-Backup' -PortGroup 'dvPG_3534_10.2.170.0_24' -IP $vmk2IP -SubnetMask 255.255.255.0 + } + 'DCN Datacenter' { + } + 'Grand Forks Vantis' { + } +} + +# set vmkernel capabilities +Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk0 | Set-VMHostNetworkAdapter -VSphereReplicationEnabled $true -VSphereReplicationNfcEnabled $true -Confirm:$false +Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk1 | Set-VMHostNetworkAdapter -VMotionEnabled $true -Confirm:$false +Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk2 | Set-VMHostNetworkAdapter -VSphereBackupNfcEnabled $true -Confirm:$false + +# core dump - disable coredump file, enable network coredump +$CoreDumpArgs = $EsxCli.system.coredump.file.set.CreateArgs() +$CoreDumpArgs.enable = $false +$EsxCli.system.coredump.file.set.invoke($CoreDumpArgs) +$CoreDumpArgs = $EsxCli.system.coredump.network.set.CreateArgs() +$CoreDumpArgs.serverport = 6500 +$CoreDumpArgs.interfacename = 'vmk0' +switch ($VMHostDatacenter.Name) { + 'Primary Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.25' } + 'Secondary Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.26' } + 'DCN Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.25' } + 'Grand Forks Vantis' { $CoreDumpArgs.serveripv4 = '10.8.145.25' } +} +#$CoreDumpArgs.serveripv4 = '10.8.145.25' +$EsxCli.system.coredump.network.set.invoke($CoreDumpArgs) +$CoreDumpArgs = $EsxCli.system.coredump.network.set.CreateArgs() +$CoreDumpArgs.enable = $true +$EsxCli.system.coredump.network.set.invoke($CoreDumpArgs) +$EsxCli.system.coredump.network.get.invoke() + +# ntp - set NTP server and set service to start/stop with host +Get-VMHost -Name $VMHostName | Add-VMHostNtpServer 10.2.7.40, 10.10.10.10 +Get-VMHost -Name $VMHostName | Get-VMHostService | where { $_.Key -eq "ntpd" } | Set-VMHostService -Policy On + +# static route for backups +$ParamsToAdd = @{ + network = '10.2.169.0/24' +} +switch ($VMHostDatacenter.Name) { + 'Primary Datacenter' { $ParamsToAdd.gateway = '10.2.170.1' } + 'Secondary Datacenter' { $ParamsToAdd.gateway = '10.2.170.1' } + 'DCN Datacenter' { $CoreDumpArgs.serveripv4 = '10.2.118.241' } + 'Grand Forks Vantis' { $CoreDumpArgs.serveripv4 = '' } +} +$EsxCli.network.ip.route.ipv4.add.Invoke($ParamsToAdd) + +<#$params = @{ + network = '10.2.169.0/24' ## check subnet mask, should be /24 after collapsing the Cohesity subnets + gateway = '10.2.170.1' ## General 10.2.170.1, VDI 10.2.15.1, TEST 10.2.168.241 # DCN 10.2.118.241 +} #> +#$x = $esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'} +#$x | Add-Member -Name "Name" -MemberType NoteProperty -Value $VMHost.Name +#$null = $result.Add($x) + +<## to remove static route +$paramsToRemove = @{ + network = '10.2.169.0/24' + gateway = '10.2.170.1' +} +$EsxCli.network.ip.route.ipv4.remove.Invoke($paramsToRemove) +##> + +# sshServer firewall +### 10.8.145.46 itdvmutilp3, 10.29.40.0/23 adminvpn +Get-VMHost -Name $VMHostName | Get-VMHostFirewallException -Name 'SSH Server' | Set-VMHostFirewallException -Enabled $true +$sshArgs = $EsxCli.network.firewall.ruleset.set.CreateArgs() +$sshArgs.enabled = $true +$sshArgs.allowedall = $false +$sshArgs.rulesetid = 'sshServer' +$EsxCli.network.firewall.ruleset.set.invoke($sshArgs) +$AllowedIpArgs = $EsxCli.network.firewall.ruleset.allowedip.add.CreateArgs() +$AllowedIpArgs.ipaddress = "10.8.145.46" +$AllowedIpArgs.rulesetid = 'sshServer' +$EsxCli.network.firewall.ruleset.allowedip.add.invoke($AllowedIpArgs) +$AllowedIpArgs = $EsxCli.network.firewall.ruleset.allowedip.add.CreateArgs() +$AllowedIpArgs.ipaddress = "10.29.40.0/23" +$AllowedIpArgs.rulesetid = 'sshServer' +$EsxCli.network.firewall.ruleset.allowedip.add.invoke($AllowedIpArgs) + +(Get-VMHost -Name $VMHostName | Get-View).EnterLockdownMode() + + + +<#ForEach($VMHostName in $VMHostNames){ + write-warning $VMHostName + $EsxCli = Get-EsxCli -VMHost $VMHostName -V2 + $esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'} +}#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-TestLocalCreds.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-TestLocalCreds.ps1 new file mode 100644 index 0000000..db8b2c9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMHost-TestLocalCreds.ps1 @@ -0,0 +1,38 @@ +$VMHostNames = @" +itdvmmdnwin11.nd.gov +itdvmmdnwin12.nd.gov +"@ +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames + +ForEach ($VMHostName in $VMHostNames) { + $RootCred = $null + $RootCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred + + Disable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode + + $null = Connect-VIServer $VMHostName -Credential $RootCred + + If (-not ($?)) { + Write-Warning ($VMHostName + " password failed") + } + else { + Disconnect-VIServer $VMHostName -Force -Confirm:$false + } + Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode +} + + +$VMHostNames = @" +itdvmmdnwin11.nd.gov +itdvmmdnwin12.nd.gov +"@ +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames +$VmDefaultCred = Get-Secret VMDefault +ForEach($VMHostName in $VMHostNames){ + Disable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode + $VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred + Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred + Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password + Disconnect-VIServer -Server $VMHostname -Confirm:$false + Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhost-MetadataGeneration.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhost-MetadataGeneration.ps1 new file mode 100644 index 0000000..7c13f39 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhost-MetadataGeneration.ps1 @@ -0,0 +1,3 @@ +Get-VMHost | Select-Object Name,Model,MemoryTotalGB,ProcessorType,@{n='NumCpuPackages';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuPackages}},@{n='CoresPerSocket';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuCores / $_.ExtensionData.Hardware.CpuInfo.NumCpuPackages}},@{n='NumCpuCores';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuCores}} + +Get-Cluster | Where-Object {$_.Name -notlike "WINDOWS*" -or $_.Name -notlike "PS*" -or $_.Name -notlike "SQL*"} | Get-VM | Where-Object {$_.Guest.OSFullName -match "Windows"} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-BL460.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-BL460.ps1 new file mode 100644 index 0000000..564b30d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-BL460.ps1 @@ -0,0 +1,363 @@ +#---------------------------------------------------------------------------------------------------------------------------------------------------- +$creds = Get-Credential +#Connect VC1 +Connect-VIServer 'itdvmvc1.nd.gov' -Credential $creds +#Connect VC2 +Connect-VIServer 'itdvmvc2.nd.gov' -Credential $creds +#Connect VCT1 +Connect-VIServer 'itdvmvct1.nd.gov' -Credential $creds +#Connect VCT2 +Connect-VIServer 'itdvmvct2.nd.gov' -Credential $creds +#Connect OneView +Connect-HPOVMgmt -Hostname 'itdoneviewp1.nd.gov' -Credential $creds -LoginAcknowledge +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#VMHosts to Patch +$VMHostNames = @" +itdvmmdnav04.nd.gov +itdvmmdnav05.nd.gov +"@ +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Disable Alarms and Disconnect CDROM +foreach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost $VMHostName + #$VMHostParent = $GetVMHost.Parent + $HostCluster = Get-Cluster -VMHost $VMHostName + <#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec + $NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo + $NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy + $NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true + $HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true) + #> + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } + $VMs = $GetVMHost | Get-VM + #Disconnect CDROM and/or VMtools ISO + foreach ($VM in $VMs) { + $GetVM = Get-VM $VM + $CDDrive = $GetVM | Get-CDDrive + if ($CDDrive | Where-Object { $_.IsoPath -Like "*vmware/isoimages*" }) { + $GetVM | Dismount-Tools + #$CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + elseif ($CDDrive.HostDevice -Like "*drive*") { + $CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + } + $GetVMHost = $null +} +#Move Powered Off VMs +foreach ($VMHostName in $VMHostNames) { + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostParent = $VMHostDetails.Parent.Name + $VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1 + $VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff" + If ($VMsPoweredOff) { Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate } +} +#Enter Maintenance Mode +Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync +Start-Sleep -Seconds 10 + +#Monitor +Get-VMHost -Name $VMHostNames | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } } + +# Move to HostUpgradesInProgress Folder +Get-VMHost -Name $VMHostNames | Move-VMHost -Destination "HostUpgradesInProgress" +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Shutdown Host +Stop-VMHost -VMHost $VMHostNames -Confirm:$false +#Monitor +Get-VMHost $VMHostNames | Select-Object -Property Name, ConnectionState, CpuUsageMhz +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Verify OneView Server Profile Power State -EQ Off +<#foreach ($VMHostName in $VMHostNames){ + $HPOVServerProfile = Get-HPOVServerProfile -Name $VMHostName + $HPOVServer = $HPOVServerProfile | Get-HPOVServer + if ($HPOVServer.powerState -EQ "On"){ + $HPOVServer | Update-HPOVServer -Async + } + }#> + +# ensure server power is off +foreach ($VMHostName in $VMHostNames) { + $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName + $HPOVServer = $HPOVServerProfile | Get-OVServer + if ($HPOVServer.powerState -EQ "On") { + $HPOVServer | Update-OVServer -Async + } +} +#Monitor +foreach ($VMHostName in $VMHostNames) { + Get-OVServer -ServerName $VMHostName | Select-Object serverName, powerState +} +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Join OneView Template to Host +$HPOVtemplates = Get-OVServerProfileTemplate +foreach ($VMHostName in $VMHostNames) { + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0] + switch ($VMHostVIserver) { + itdvmvc1.nd.gov { $HPOVtemplDataCenter = "BIS" } + Default { $HPOVtemplDataCenter = "MDN" } + } + $VMHostParent = $VMHostDetails.Parent.Name + <#switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) { + Avaya { $HPOVtemplType = "Avaya" } + TEL { $HPOVtemplType = "Avaya" } + DCN { $HPOVtemplType = "DCN" } + DES { $HPOVtemplType = "DES" } + Oracle { $HPOVtemplType = "Oracle" } + SQL { $HPOVtemplType = "SQL" } + SQL2-D { $HPOVtemplType = "SQL" } + TEST { $HPOVtemplType = "Test" } + Default { $HPOVtemplType = "General" } + }#> + + If($VMHostName -like "*sql*" -or $VMHostName -like "*ora*"){ + $HPOVtemplType = "SQL" + } + Else{ + $HPOVtemplType = "General" + } + + $HPOVtemplModel = $VMHostDetails.Model.Split()[2] + $NewHPOVtempl = $HPOVtemplates | Where-Object { $_.Name -Like "*$HPOVtemplDataCenter*" -and $_.Name -Like "*$HPOVtemplType*" -and $_.Name -Like "*$HPOVtemplModel*" } | Sort-Object Name | Select-Object -Last 1 + Join-OVServerProfileToTemplate -Template $NewHPOVtempl -ServerProfile $VMHostName +} +#Monitor +foreach ($VMHostName in $VMHostNames) { + Get-OVServerProfile -Name $VMHostName +} +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Check iLO Health Status +<# + foreach ($VMHostName in $VMHostNames){ + $iLOHostName = ($VMHostName.split(".")[0])+"lo.nd.gov" + $iLoConnection = Connect-HPEiLO $iLOHostName -Credential $creds + Get-HPEiLOHealthSummary -Connection $iLoConnection | Select-Object Hostname,Status + Disconnect-HPEiLO -Connection $iLoConnection + }#> +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Update OneView Server Template +foreach ($VMHostName in $VMHostNames) { + Get-OVServerProfile -Name $VMHostName | Update-OVServerProfile -Confirm:$false -Async + Start-Sleep -Seconds 30 +} +#powershell finished in 20m, but continued to run for 36min +#Monitor +foreach ($VMHostName in $VMHostNames) { + Get-OVServerProfile -Name $VMHostName | Select-Object Name, State +} +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Start OneView Server Profile +foreach ($VMHostName in $VMHostNames) { + $wait = $true + While ($wait -EQ $true) { + $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName + if ($HPOVServerProfile.Status -NE "OK") { + $wait = $true + Start-Sleep -Seconds 60 + } + else { + $wait = $false + $HPOVServerProfile | Start-OVServer -Async + } + } +} +#Monitor +foreach ($VMHostName in $VMHostNames) { + Get-OVServerProfile -Name $VMHostName +} +#---------------------------------------------------------------------------------------------------------------------------------------------------- +# manual full install of v7.0u3 now +<# ISO connected from workstation via iLO - + boot @ 9:43 + initial install screen @ 10:00 + ISO connect from vmutil + boot @ 10:01 + initial install screen @ 10:10 +#> + +# remove old from vcenter inventory +ForEach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostName | Remove-VMHost -Confirm:$false + start-sleep -Seconds 3 +} + +# add to vcenter +$VmDefaultCred = Get-Secret VMDefault +ForEach ($VMHostName in $VMHostNames) { + Add-VMHost -Name $VMHostName -Credential $VmDefaultCred -Location "HostUpgradesInProgress" -Force -Server $ViServer + Start-Sleep -Seconds 3 +} + +# license host +Get-VMHost -Name $VMHostNames | Set-VMHost -LicenseKey '2M63H-8T391-P8YG4-00MR4-ARNP0' + +# set maintenance and disable alarms +Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync +ForEach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost -Name $VMHostname + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } +} + +# Set root password +ForEach ($VMHostName in $VMHostNames) { + $VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred + Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred + Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password + Disconnect-VIServer -Server $VMHostname -Confirm:$false + <#$EsxCli = Get-EsxCli -VMHost $VMHostName + /vmfs/volumes/5a737d2f-b45bb27d-7f74-e0071befea78/Scratch/itdbisvm-dcn01 + + $args = $EsxCli.system.account.set.CreateArgs() + $args.id = "root" + $args.password = $VMHostCred.GetNetworkCredential().Password + $args.passwordconfirmation = $VMHostCred.GetNetworkCredential().Password + $output = $EsxCli.system.account.set.invoke(@{ + id = $VMHostCred.UserName; + password = $VMHostCred.GetNetworkCredential().Password; + passwordconfirmation = $VMHostCred.GetNetworkCredential().Password; + })#> +} + +#Patch via Update Manager +#Monitor ConnectionState +foreach ($VMHostName in $VMHostNames) { + $VMHost = Get-VMHost $VMHostName + $VMHost | Select-Object -Property Name, ConnectionState +} + + +foreach ($VMHostName in $VMHostNames) { + $VMHost = Get-VMHost $VMHostName + $VMHostVIserver = $VMHost.Uid.Split('@')[1].Split(':')[0] + #$VMHostBaseline = Get-Baseline -Server $VMHostVIserver | Where-Object Name -Like "*ESXi 6.5.0*" + $VMHostBaselineUpgrade = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-ProLiant" } + $VMHostBaselinePatch = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3 Patch" } + $VMHostBaselineAll = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-ProLiant" -or $_.Name -EQ "7.0U3 Patch"} + Attach-Baseline -Baseline $VMHostBaselineUpgrade -Entity $VMHost + Attach-Baseline -Baseline $VMHostBaselinePatch -Entity $VMHost +} +#Remediate Baseline --- Do this in the GUI with all hosts in the same folder +<# +ForEach($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Scan-Inventory -Entity $VMHost +} + +ForEach($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Stage-Patch -Entity $VMHost -Baseline $VMhostBaselineUpgrade + Stage-Patch -Entity $VMHost -Baseline $VMhostBaselinePatch -RunASync +} + +ForEach($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineAll -RunAsync -Confirm:$false +}#> + +#Monitor +Get-Task | Where-Object Name -Like "*Remediate*" +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Attach Host Profile and Test Compliance +foreach ($VMHostName in $VMHostNames) { + $CurrentHostProfiles = Get-VMHostProfile + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0] + switch ($VMHostVIserver) { + itdvmvc1.nd.gov { $VMHostVIserver = "BIS" } + Default { $VMHostVIServer = "MDN" } + } + $VMHostParent = $VMHostDetails.Parent.Name + switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) { + Avaya { $VMHostProfile = "Avaya" } + TEL { $VMHostProfile = "TEL" } + Default { $VMHostProfile = "General" } + } + #$VMHostBuild = $VMHostDetails.Build + #$VMHostVersion = $VMHostDetails.Version + #$VMHostProfileName = $CurrentHostProfiles | Where-Object {$_.Name -Like "*$VMHostVIserver*" -and $_.Name -Like "*$VMHostVersion*" -and $_.Name -Like "*$VMHostBuild*" -and $_.Name -Like "*$VMHostProfile*"} | Sort-Object Name | Select-Object -First 1 + $VMHostProfileName = $CurrentHostProfiles | Where-Object { $_.Name -like "*$VMHostVIserver*" -and $_.Name -Like "*7.0.3*" -and $_.Name -like "*$VMHostProfile*" -and $_.Name -like "*BL460c*" } + Invoke-VMHostProfile -Entity $VMHostDetails -Profile $VMHostProfileName -AssociateOnly -Confirm:$false +} +# import host customization csv +foreach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostName | Test-VMHostProfileCompliance +} +#Remediate Host Profile +foreach ($VMHostName in $VMHostNames) { + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostProfileCompliance = $VMhostDetails | Test-VMHostProfileCompliance #### ??????? + if ($VMHostProfileCompliance.ExtensionData.ComplianceStatus -Like "*non*") { + Invoke-VMHostProfile -Entity $VMhostDetails -Confirm:$false + } + $VMhostDetails | Test-VMHostProfileCompliance +} + +# reboot hosts 0_Offline, Before Upgrade v7.0U3h +Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false + +#Test Host Profile Compliance +foreach ($VMHostName in $VMHostNames) { + Get-VMHost $VMHostName | Test-VMHostProfileCompliance +} +# maybe reboot again sometimes maybe +Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false + +#Exit Maintenance Mode and Enable Alarms +Set-VMHost -VMHost $VMHostNames -State "Connected" -RunAsync +Start-Sleep -Seconds 30 +foreach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost $VMHostName + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true) + } + $GetVMHost = $null +} +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#$VMCluster = Get-Cluster $VMHostParent #| Set-Cluster -HAAdmissionControlEnabled:$false -Confirm:$false +#$HAFailoverHost = Get-VMHost | Where-Object {$_.Id -Match ((Get-Cluster $VMHostParent).extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)} +#get-vmhost | where-object {$_.id -eq ($vmcluster.extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)} + +<# +foreach ($VMHostProfile in $VMHostProfiles){ + Export-VMHostProfile -FilePath $FilePath$Profile".xml" -Profile $VMHostProfile +} +Import-VMHostProfile -FilePath $FilePath"TestHostProfile.xml" -Name "Test Scripting" +#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-Synergy.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-Synergy.ps1 new file mode 100644 index 0000000..c189510 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMhostPatching-Synergy.ps1 @@ -0,0 +1,481 @@ +#---------------------------------------------------------------------------------------------------------------------------------------------------- +$creds = Get-Credential +#Connect VC1 +Connect-VIServer 'itdvmvc1.nd.gov' -Credential $creds +#Connect VC2 +Connect-VIServer 'itdvmvc2.nd.gov' -Credential $creds +#Connect VCT1 +Connect-VIServer 'itdvmvct1.nd.gov' -Credential $creds +#Connect VCT2 +Connect-VIServer 'itdvmvct2.nd.gov' -Credential $creds +#Connect OneView +Connect-HPOVMgmt -Hostname 'itdoneviewp1.nd.gov' -Credential $creds -LoginAcknowledge +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#VMHosts to Patch +$VMHostNames = @" +itdvmbiswin19.nd.gov +itdvmbislin10.nd.gov +itdvmbiswas08.nd.gov +itdvmbissql14.nd.gov +itdvmbissql15.nd.gov +itdvmbistel09.nd.gov +itdvmbisvapp04.nd.gov +itdvmbissqla02.nd.gov +itdvmbiswas09.nd.gov +itdvmbiswin08.nd.gov +itdvmbiswin14.nd.gov +itdvmbisps18.nd.gov +"@ +$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Disable Alarms and Disconnect CDROM +foreach ($VMHostName in $VMHostNames) { + Write-Warning -Message ("Start $VMHostName") + $GetVMHost = Get-VMHost $VMHostName + #$VMHostParent = $GetVMHost.Parent + #$HostCluster = Get-Cluster -VMHost $VMHostName + <#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec + $NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo + $NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy + $NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true + $HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true) + #> + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } + $VMs = $GetVMHost | Get-VM + #Disconnect CDROM and/or VMtools ISO + + foreach ($VM in $VMs) { + $GetVM = Get-VM $VM + $CDDrive = $GetVM | Get-CDDrive + if ($CDDrive | Where-Object { $_.IsoPath -Like "*vmware/isoimages*" }) { + $GetVM | Dismount-Tools + #$CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + elseif ($CDDrive.HostDevice -Like "*drive*") { + $CDDrive | Set-CDDrive -NoMedia -Confirm:$false + } + } + $GetVMHost = $null +} +#Move Powered Off VMs +foreach ($VMHostName in $VMHostNames) { + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostParent = $VMHostDetails.Parent.Name + $VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1 + $VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff" + If ($VMsPoweredOff) { Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate } +} +#Enter Maintenance Mode +Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync + +#Monitor +Get-VMHost -Name $VMHostNames | Sort-Object Name | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } } + +# Move to HostUpgradesInProgress Folder ??? -- if host is moved out of the cluster, may break affinity rules +#Get-VMHost -Name $VMHostNames | Move-VMHost -Destination "HostUpgradesInProgress" +#---------------------------------------------------------------------------------------------------------------------------------------------------- +#Shutdown Host +Stop-VMHost -VMHost $VMHostNames -Confirm:$false +#Monitor +Get-VMHost $VMHostNames | Select-Object -Property Name, ConnectionState, CpuUsageMhz +#---------------------------------------------------------------------------------------------------------------------------------------------------- +##Verify OneView Server Profile Power State -EQ Off +#<#foreach ($VMHostName in $VMHostNames){ +# $HPOVServerProfile = Get-HPOVServerProfile -Name $VMHostName +# $HPOVServer = $HPOVServerProfile | Get-HPOVServer +# if ($HPOVServer.powerState -EQ "On"){ +# $HPOVServer | Update-HPOVServer -Async +# } +# }#> +# +## ensure server power is off +#foreach ($VMHostName in $VMHostNames) { +# $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName.Split('.')[0] +# $HPOVServer = $HPOVServerProfile | Get-OVServer +# if ($HPOVServer.powerState -EQ "On") { +# $HPOVServer | Update-OVServer -Async +# } +#} +##Monitor +#foreach ($VMHostName in $VMHostNames) { +# Get-OVServer -ServerName $VMHostName.split('.')[0] | Select-Object serverName, powerState +#} +##---------------------------------------------------------------------------------------------------------------------------------------------------- +##Join OneView Template to Host +#$HPOVtemplates = Get-OVServerProfileTemplate +#foreach ($VMHostName in $VMHostNames) { +# $VMHostDetails = Get-VMHost -Name $VMHostName +# <#$VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0] +# switch ($VMHostVIserver) { +# itdvmvc1.nd.gov { $HPOVtemplDataCenter = "BIS" } +# Default { $HPOVtemplDataCenter = "MDN" } +# }#> +# $VMHostParent = $VMHostDetails.Parent.Name +# switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) { +# Avaya { $HPOVtemplType = "Avaya" } +# TEL { $HPOVtemplType = "Avaya" } +# DCN { $HPOVtemplType = "DCN" } +# DES { $HPOVtemplType = "DES" } +# Oracle { $HPOVtemplType = "Oracle" } +# SQL { $HPOVtemplType = "SQL" } # database +# SQL2-D { $HPOVtemplType = "SQL" } +# TEST { $HPOVtemplType = "Test" } +# Default { $HPOVtemplType = "General" } +# } +# $HPOVtemplModel = $VMHostDetails.Model.Split()[2] +# $NewHPOVtempl = $HPOVtemplates | Where-Object { $_.Name -Like "*$HPOVtemplDataCenter*" -and $_.Name -Like "*$HPOVtemplType*" -and $_.Name -Like "*$HPOVtemplModel*" } | Sort-Object Name | Select-Object -Last 1 +# Join-OVServerProfileToTemplate -Template $NewHPOVtempl -ServerProfile $VMHostName.Split('.')[0] +#} +##Monitor +#foreach ($VMHostName in $VMHostNames) { +# Get-OVServerProfile -Name $VMHostName.Split('.')[0] +#} +##---------------------------------------------------------------------------------------------------------------------------------------------------- +##Check iLO Health Status +#<# +# foreach ($VMHostName in $VMHostNames){ +# $iLOHostName = ($VMHostName.split(".")[0])+"lo.nd.gov" +# $iLoConnection = Connect-HPEiLO $iLOHostName -Credential $creds +# Get-HPEiLOHealthSummary -Connection $iLoConnection | Select-Object Hostname,Status +# Disconnect-HPEiLO -Connection $iLoConnection +# }#> +##---------------------------------------------------------------------------------------------------------------------------------------------------- +##Update OneView Server Template +#foreach ($VMHostName in $VMHostNames) { +# Get-OVServerProfile -Name $VMHostName.Split('.')[0] | Update-OVServerProfile -Confirm:$false -Async +# Start-Sleep -Seconds 30 +#} +##powershell finished in 20m, but continued to run for 36min +##Monitor +#foreach ($VMHostName in $VMHostNames) { +# Get-OVServerProfile -Name $VMHostName | Select-Object Name, State +#} +##---------------------------------------------------------------------------------------------------------------------------------------------------- +##Start OneView Server Profile +#foreach ($VMHostName in $VMHostNames) { +# #$wait = $true +# #While ($wait -EQ $true) { +# $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName.split('.')[0] +# #if ($HPOVServerProfile.Status -NE "OK") { +# #$wait = $true +# #Start-Sleep -Seconds 60 +# #} +# #else { +# #$wait = $false +# $HPOVServerProfile | Start-OVServer -Async +# Start-Sleep -Seconds 5 +# #} +# #} +#} +# +## mount ISO in iLO +# +##Monitor +#foreach ($VMHostName in $VMHostNames) { +# Get-OVServerProfile -Name $VMHostName.Split('.')[0] +#} +##---------------------------------------------------------------------------------------------------------------------------------------------------- +## manual full install of v7.0u3 now +#<# ISO connected from workstation via iLO - +# boot @ 9:43 +# initial install screen @ 10:00 +# ISO connect from vmutil +# boot @ 10:01 +# initial install screen @ 10:10 +##> + +# remove old from vcenter inventory +ForEach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostNames | Remove-VMHost -Confirm:$false +} + +# add to vcenter +$VmDefaultCred = Get-Secret VMDefault +ForEach ($VMHostName in $VMHostNames) { + Add-VMHost -Name $VMHostName -Credential $VmDefaultCred -Location "Secondary Datacenter" -Server $VIServer -Force +} + +# license host +Get-VMHost -Name $VMHostNames | Set-VMHost -LicenseKey 'M04W3-FEJ0H-P8J61-LMRKH-C4D1K' + +# not avaya '2M63H-8T391-P8YG4-00MR4-ARNP0' +# avaya '3001L-FT19L-28PGX-099A2-2XQNH' +# VDI Desktop 'L56AQ-0VH1K-488GT-0NQU2-ADG64' +Start-Sleep -seconds 3 + +# set maintenance and disable alarms +Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync +ForEach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost -Name $VMHostname + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } +} + +# Set root password +ForEach ($VMHostName in $VMHostNames) { + $VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred + Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred + Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password + Disconnect-VIServer -Server $VMHostname -Confirm:$false + <# + $EsxCli = Get-EsxCli -VMHost $VMHostName + $args = $EsxCli.system.account.set.CreateArgs() + $args.id = "root" + $args.password = $VMHostCred.GetNetworkCredential().Password + $args.passwordconfirmation = $VMHostCred.GetNetworkCredential().Password + $output = $EsxCli.system.account.set.invoke(@{ + id = $VMHostCred.UserName; + password = $VMHostCred.GetNetworkCredential().Password; + passwordconfirmation = $VMHostCred.GetNetworkCredential().Password; + }) + #> +} + +# M.2 drives only, remove datastore1 from vmhost .... will get errors but still work +ForEach($VMHostName in $VMHostNames){ + Remove-Datastore -Datastore "datastore1*" -VMHost $VMHostName -Confirm:$false +} + + +#Patch via Update Manager +#Monitor ConnectionState +foreach ($VMHostName in $VMHostNames) { + $VMHost = Get-VMHost $VMHostName + $VMHost | Select-Object -Property Name, ConnectionState +} + + +foreach ($VMHostName in $VMHostNames) { + $VMHost = Get-VMHost $VMHostName + $VMHostVIserver = $VMHost.Uid.Split('@')[1].Split(':')[0] + #$VMHostBaseline = Get-Baseline -Server $VMHostVIserver | Where-Object Name -Like "*ESXi 6.5.0*" + $VMHostBaselineUpgrade = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Synergy" } + $VMHostBaselinePatch = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Patch" } + $VMHostBaselineTools = Get-Baseline -Server $VMHostVIserver | Where-Object {$_.Name -EQ "VMware Tools"} + $VMHostBaselineAll = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Synergy" -or $_.Name -EQ "vSphere 7.0U3-Patch" -or $_.Name -EQ "VMware Tools"} + Attach-Baseline -Baseline $VMHostBaselineUpgrade -Entity $VMHost + Attach-Baseline -Baseline $VMHostBaselinePatch -Entity $VMHost + Attach-Baseline -Baseline $VMHostBaselineTools -Entity $VMHost +} +#Remediate Baseline # do manually with VUM on the Host Folder + +ForEach($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Scan-Inventory -Entity $VMHost -RunASync +} + +Foreach ($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + #Stage-Patch -Entity $VMHost -Baseline $VMhostBaselineUpgrade -RunAsync + Stage-Patch -Entity $VMHost -Baseline $VMhostBaselinePatch -RunASync + Stage-Patch -Entity $VMHost -Baseline $VMHostBaselineTools -RunASync +} + +ForEach ($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselinePatch -RunAsync -Confirm:$false +} + +ForEach ($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineTools -RunAsync -Confirm:$false +}#> + +ForEach ($VMHostName in $VMHostNames){ + $VMHost = Get-VMHost $VMHostName + Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineAll -RunAsync -Confirm:$false +} + +#Monitor +Get-Task | Where-Object Name -Like "*Remediate*" +#---------------------------------------------------------------------------------------------------------------------------------------------------- +<# 2024/07/30 attach, test, invoke that works + +$VMHosts = Get-Datacenter -Name Primary* | Get-VMHost | where-object Name -notlike "*av*" +ForEach($VMHost in $VMHosts){ + Write-Warning -Message ("Start" + $VMHost.Name) + $VMHost | Invoke-VMHostProfile -Profile $HostProfile -AssociateOnly -Confirm:$false + $VMHost | Test-VMHostProfileCompliance +} + +ForEach($VMHost in $VMHosts){ + $VMHost | Invoke-VMHostProfile -Confirm:$false +} + + +#> + +#Attach Host Profile and Test Compliance +foreach ($VMHostName in $VMHostNames) { + $CurrentHostProfiles = Get-VMHostProfile + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0] + switch ($VMHostVIserver) { + itdvmvc1.nd.gov { $VMHostVIserver = "BIS" } + Default { $VMHostVIServer = "MDN" } + } + $VMHostParent = $VMHostDetails.Parent.Name + switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) { + Avaya { $VMHostProfile = "Avaya" } + TEL { $VMHostProfile = "TEL" } + Default { $VMHostProfile = "General" } + } + #$VMHostBuild = $VMHostDetails.Build + #$VMHostVersion = $VMHostDetails.Version + #$VMHostProfileName = $CurrentHostProfiles | Where-Object {$_.Name -Like "*$VMHostVIserver*" -and $_.Name -Like "*$VMHostVersion*" -and $_.Name -Like "*$VMHostBuild*" -and $_.Name -Like "*$VMHostProfile*"} | Sort-Object Name | Select-Object -First 1 + $VMHostProfileName = $CurrentHostProfiles | Where-Object { $_.Name -like "*$VMHostVIserver*" -and $_.Name -Like "*7.0.3*" -and $_.Name -like "*$VMHostProfile*" -and $_.Name -like "*Synergy*" } | Sort-Object -Descending Name | Select -First 1 + Invoke-VMHostProfile -Entity $VMHostDetails -Profile $VMHostProfileName -AssociateOnly -Confirm:$false +} +# import host customization csv now + +# then continue +foreach ($VMHostName in $VMHostNames) { + Get-VMHost -Name $VMHostName | Test-VMHostProfileCompliance +} +#Remediate Host Profile +foreach ($VMHostName in $VMHostNames) { + $VMHostDetails = Get-VMHost -Name $VMHostName + $VMHostProfileCompliance = $VMhostDetails | Test-VMHostProfileCompliance #### ??????? + if ($VMHostProfileCompliance.ExtensionData.ComplianceStatus -Like "*non*") { + Invoke-VMHostProfile -Entity $VMhostDetails -Confirm:$false + } + $VMhostDetails | Test-VMHostProfileCompliance +} +#Test Host Profile Compliance +foreach ($VMHostName in $VMHostNames) { + Get-VMHost $VMHostName | Test-VMHostProfileCompliance +} + +# Host requires reboot before previously applied configuration changes will take effect +Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false + +#Test Host Profile Compliance again +foreach ($VMHostName in $VMHostNames) { + Get-VMHost $VMHostName | Test-VMHostProfileCompliance +} + +# move hosts back to their clusters +ForEach($VMHostName in $VMHostNames){ + switch ($VMHostName.substring(8).split('.')[0].substring(0,2)){ + 'ps' {$ClusterStr = "PS"} + } + switch ($VMHostVIserver){ + 'itdvmvc1.nd.gov' {$ClusterInt = 1} + 'itdvmvc2.nd.gov' {$ClusterInt = 2} + } + $ClusterName = $ClusterStr + $ClusterInt + Move-VMHost -VMHost $VMHostName -Destination (Get-Cluster -Name $ClusterName) +} + +# restart again because HA is being weird +Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false + +# monitor +Get-VMHost -Name $VMHostNames + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#Monitor +Get-VMHost -Name $VMHostNames | Sort-Object Name | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } } + +#Exit Maintenance Mode and Enable Alarms +ForEach($VMHostName in $VMHostNames){ + Set-VMHost -VMHost $VMHostName -State "Connected" -RunAsync + Start-Sleep -Seconds 2 +} + +foreach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost $VMHostName + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true) + } + $GetVMHost = $null +} + + + + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#---------------------------------------------------------------------------------------------------------------------------------------------------- + +#$VMCluster = Get-Cluster $VMHostParent #| Set-Cluster -HAAdmissionControlEnabled:$false -Confirm:$false +#$HAFailoverHost = Get-VMHost | Where-Object {$_.Id -Match ((Get-Cluster $VMHostParent).extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)} +#get-vmhost | where-object {$_.id -eq ($vmcluster.extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)} + +<# +foreach ($VMHostProfile in $VMHostProfiles){ + Export-VMHostProfile -FilePath $FilePath$Profile".xml" -Profile $VMHostProfile +} +Import-VMHostProfile -FilePath $FilePath"TestHostProfile.xml" -Name "Test Scripting" +#> +#Get-OVServer -ov x +#$x | select Name,processorType,processorCount,processorCoreCount,serialnumber,memorymb,generation + + + +## disable alarms entire datacenter +$VMHostNames=(Get-Datacenter primary* | Get-VMHost).Name +foreach ($VMHostName in $VMHostNames) { + Write-Warning -Message ("Start $VMHostName") + $GetVMHost = Get-VMHost $VMHostName + #$VMHostParent = $GetVMHost.Parent + #$HostCluster = Get-Cluster -VMHost $VMHostName + <#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec + $NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo + $NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy + $NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true + $HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true) + #> + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $true) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false) + } +} + +## enable alarms for entire datacenter +$VMHostNames = (Get-VMHost).Name +foreach ($VMHostName in $VMHostNames) { + $GetVMHost = Get-VMHost $VMHostName + $VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0] + $alarmMgr = Get-View AlarmManager -Server $VIServer + $alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled + if ($alarmEnabled -eq $false) { + $alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true) + } + $GetVMHost = $null +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-AutoBuildLoop.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-AutoBuildLoop.ps1 new file mode 100644 index 0000000..6fc5d75 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-AutoBuildLoop.ps1 @@ -0,0 +1,971 @@ +$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto +$StdCred = $IaasAuto +$PrvCred = $IaasAuto + +$FQDNs = @" +itdzmtest111.ndtestdev.nd.dev +"@ + +$FQDNs = ConvertTo-Array -MultiLineString $FQDNs + +ForEach ($FQDN in $FQDNs) { + Write-Warning "[$FQDN]:Start" + $SPCred = $StdCred + $ADCred = $PrvCred + $PSCred = $PrvCred + $VMCred = $PrvCred + $CcmCred = $PrvCred + #> + <# Get Credentials + + $SPCred = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite' + $ADCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $PSCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation' + $IBCred = New-Object System.Management.Automation.PSCredential ($PSCred.UserName.split('\')[1], $ADCred.Password) + $VMCred = Get-AutomationPSCredential -Name 'VMware Auto' + $CcmCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'#> + #> + Clear-DnsClientCache + $SharePointList = Get-ITDVMwareSharePointVMGuestList -Credential $SPCred + Write-Warning ("SPList count: " + $SharePointList.count) + $SPItem = $SharePointList | Where-Object Title -EQ $FQDN + If ($null -eq $SPItem.Cluster) { + Write-Error "VMware Cluster not specified in SharePoint" + Stop + } + Write-Warning $SPItem + $HostName = $FQDN.split('.')[0] + + # Infoblox + [Net.IpAddress]$NetworkId = $SPItem.CIDR.split('/')[0] + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + $SubnetMaskInt = $SPItem.Cidr.split('/')[1] + $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) + [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() + $IPSplit = $SPItem.Cidr.Split('.') + [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($SPItem.Cidr.split('/')[0].split('.')[-1] -as [int]) + 1) ) + <# + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose "IP Address and CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop + } + #> + + If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } + } + Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $SPItem.Title -CIDR $SPItem.CIDR -Credential $RadiusCred + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress + } + #> + If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop + } + + # Passwordstate BB before baseline, AB after baseline + If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" + } + Else { + $PasswordStateList = "CSRC" + } + + $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred + #$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) + #$GuestCredential = $GuestCredentialBB + + # VMware + Connect-ITDvCenter -Credential $VMCred + If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Stop + Stop + } + + switch ($SPItem.Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($SPItem.LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($SPItem.LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + } + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen" + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } + <# + "DCN1" { + $ViServer = 'itdvmvc1.nd.gov' + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-DCN-vMotion-Data" + $DiskStorageFormat = 'Thin' + } + #> + } + + # verify disk will fit + + $DiskTotal = $SPItem.Disk1 + $SPItem.Disk2 + $SPItem.Disk3 + If ($DatastoreCluster) { + } + Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $SPItem.Cluster + "*") + } + $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) + If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + } + else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop + } + + $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + + switch ($SPItem.OS) { + "Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2019 Datacenter (64-Bit)" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2022 Datacenter (64-Bit)" { $Template = "Windows Server 2022 Standard" } + Default { Write-Error "Invalid template" -ErrorAction Stop } + } + + $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch + $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $SPItem.Vlan_Id + "*") + If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop + } + If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop + } + + $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) + Write-Warning "NewOSSpecName = $NewOSSpecName" + Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + + Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + + $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer + <# + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + $NewVMParams + + New-VM @NewVMParams + #> + + #Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294 + # seems fixed on 2022/07/01 + try { + Write-Warning $FQDN + Write-Warning $ComputeCluster.Name + Write-Warning $DatastoreCluster + Write-Warning $DiskStorageFormat + Write-Warning $Template + Write-Warning $FolderLocation + Write-Warning $OSSpec + New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec + } + catch { + Stop + Stop + } + + #If (!($BuildError)) { + $VM = Get-VM -Name $FQDN + + # Ensure CPU/Memory Hot-Add Enabled + $vmView = $VM | Get-View + $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $vmOptValCPU = New-Object VMware.Vim.OptionValue + $vmOptValMem = New-Object VMware.Vim.OptionValue + $vmOptValCPU.Key = "vcpu.hotadd" + $vmOptValMem.Key = "mem.hotadd" + $vmOptValCPU.Value = "true" + $vmOptValMem.Value = "true" + $vmConfigSpec.ExtraConfig += $vmOptValCPU + $vmConfigSpec.ExtraConfig += $vmOptValMem + $vmView.ReconfigVM($vmConfigSpec) + + # Set CPU, Memory, Network + $VM | Set-VM -NumCpu $SPItem.Processors -MemoryGB $SPItem.RAM -Confirm:$false + $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + + # Power On VM + $VM | Start-VM + + # Wait for Customization to finish + $VMStarted = $false + $VMCustomizationStarted = $false + $VMCustomizationResult = $false + + While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } + } + + # Delete OS Customization Spec + # Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + + # Add/Expand Disks + Write-Warning -Message "[$FQDN]:Modify disks 1,2,3" + $VMDisk = $VM | Get-HardDisk + $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" + $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" + $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + If ($SPItem.Disk1) { + If (!$VMDisk1) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk1 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt $SPItem.Disk1) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $SPItem.Disk1 -Confirm:$false + } + } + + If ($SPItem.Disk2) { + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk2 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt $SPItem.Disk2) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $SPItem.Disk2 -Confirm:$false + } + } + + If ($SPItem.Disk3) { + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB $SPItem.Disk3 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false + } + } + + # skipping tag assignment for now + # Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose + + # Run Guest OS code + # Enable RDP with NLA - can be done with GPO + # Enable WinRM - ITD WinRM enable + # Configure Power Plan - ITD-PowerPlan-HighPerformance + # Activate Windows, KMS on-premise, Azure to Azure + # DVD Drive to Z: + # Expand C: + # Partition/Format the rest, GPT/NTFS + # Configure Page File Disk + # Enabling server manager performance monitors + # Configure Time Zone and NTP - no GPO available + # Disable Windows Firewall + # Join AD + + #Initialize-ITDServer -Credential $ADCred + + + Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking for DVD drive..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Expand C: Partition To Maximum Extent + + + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning "[$FQDN]:Start Extra Disk(s) config" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } + } + + Write-Warning "[$FQDN]:Start Page File Configuration" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } + } + + Write-Warning -Message "[$FQDN]:Enabling Remote Management..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Checking current power plan..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } + } + + + $TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + <# + Write-Verbose -Message "Beginning a time synchronization..." + + if ((Get-Service W32Time).Status -eq 'Stopped') { + Start-Service W32Time + } + + [void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update) + + [void](& w32tm.exe /resync /nowait) + + # Start background job to check time service + $tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock { + do { + $tmOut = & w32tm.exe /query /status /verbose + + Start-Sleep -Seconds 10 + } until($tmOut -match '^Last Sync Error: 0\D+$') + } + + # If after three minutes time still has not synched, move on. This usually causes no problems. + if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') { + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful." + } + else { + [void](Stop-Job -Job $tmJob) + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed." + } + #> + } + catch { + Throw $_ + Break + } + } + $TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName + $VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock + #> + Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..." + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } + } + + Write-Warning -Message "[$FQDN]:Disable Windows Firewall" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } + } + + # Active Directory + Write-Warning "[$FQDN]:Join Active Directory (if required)" + $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) + $AppName = $SPItem.AppName + switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } + } + + If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 + } + + Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) + Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force + Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date)) + #E:\AutoBuild\SCCM_Client\ + + # Check if SCCM automatically installed the SCCM client and registered it + $CcmRegistered = $false + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } + } + + Write-Warning "[$FQDN]:Register SCCM Client" + While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } + } + + Write-Warning -Message "[$FQDN]:Approve SCCM Client" + #Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL + Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } + } + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + + Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy" + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); + } + #Start-Sleep -Seconds 180 + + Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...' + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } + } + Write-Warning "[$FQDN]:End" +} + + + +Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { Get-Process -Name ccmexec*, cohesity*, cyserver*, nessus*, vmtoolsd* } + +Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" +Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-DisableLockdownVantis.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-DisableLockdownVantis.ps1 new file mode 100644 index 0000000..1344115 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-DisableLockdownVantis.ps1 @@ -0,0 +1,41 @@ + +[CmdletBinding()] +param ( +) + +begin { + +} + +process { + Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + + $VMHosts = Get-Datacenter -Name "Grand Forks Vantis" | Get-VMHost + + ForEach ($VMHost in $VMHosts) { + Write-Verbose -Message ("Start: " + $VMHost.Name) -Verbose + + $VMHostStatus = Get-ITDVMwareVMHostStatus -Name $VMHost.Name + + # if accurate, enable lockdown + If ($VMHostStatus.LockdownMode -eq 'lockdowndisabled') { + Write-Verbose -Message ("Lockdown is already disabled on " + $VMHost.Name + ", no change") -Verbose + $NoChange = $true + } + Else { + Write-Verbose -Message ("Lockdown is enabled on " + $VMHost.Name + ", disabling now") -Verbose + Disable-ITDVMwareVMHostFeature -Name $VMHost.Name -LockdownMode + + } + Start-Sleep -Seconds 5 + + # confirm lockdown is enabled + $VMHostStatusCheck = Get-ITDVMwareVMHostStatus -Name $VMHost.Name + } + + Disconnect-ITDvCenter +} + +end { + +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTicketAttemptFix.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTicketAttemptFix.ps1 new file mode 100644 index 0000000..a160bdb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTicketAttemptFix.ps1 @@ -0,0 +1,86 @@ + +[CmdletBinding()] +param ( + [switch] + $IncludeInProgress +) + +begin { + +} + +process { + New-ITDServiceNowSession -Credential $Secret:snow_vmcred -Environment Production + Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto + + If($PSBoundParameters.ContainsKey("IncludeInProgress")){ + $Filter = 'short_descriptionSTARTSWITHLockdown mode is disabled on VMware host^state=1^ORstate=2' + } Else { + $Filter = 'state=1^short_descriptionSTARTSWITHLockdown Mode is disabled on VMware host' + } + + $Incidents = Get-ITDServiceNowRecord -ItemType Incident -Filter $Filter | Sort-Object {$_.number.value} + + ForEach ($Incident in $Incidents) { + # reset variables for each loop + $VMHostName = $null + $VMHostStatus = $null + $VMHostStatusCheck = $null + $NoChange = $null + + $VMHostName = $Incident.short_description.display_value.split(' ')[-1] + + Write-Verbose -Message ("Start " + $Incident.number.display_value + " for host " + $VMHostName) -Verbose + # confirm ticket is accurate, that host has lockdown mode disabled + $VMHostStatus = Get-ITDVMwareVMHostStatus -Name $VMHostName + + # if accurate, enable lockdown + If ($VMHostStatus.LockdownMode -eq 'lockdowndisabled') { + Write-Verbose -Message ("Lockdown is still disabled on " + $VMHostName + ", enabling lockdown mode") -Verbose + Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode + } + Else { + Write-Verbose -Message ("Lockdown is already enabled on " + $VMHostName + ", no change") -Verbose + $NoChange = $true + } + Start-Sleep -Seconds 5 + + # confirm lockdown is enabled + $VMHostStatusCheck = Get-ITDVMwareVMHostStatus -Name $VMHostName + + # update ticket with current status + If ($VMHostStatusCheck.LockdownMode -eq 'lockdowndisabled') { + # update work notes if disabled + Write-Verbose -Message ("Lockdown is still disabled on " + $VMHostName + ", update incident work notes") -Verbose + $WorkNotesMsg = ("Lockdown is still disabled on " + $VMHostName + " after attempted remediation, manual review required.") + Update-ITDServiceNowRecord -ItemType Incident -Number $Incident.number.display_value -Values @{ + work_notes = $WorkNotesMsg + state = 'On Hold' + } + } + Else { + # close if enabled + If ($NoChange) { + Write-Verbose -Message ("Lockdown was already enabled on " + $VMHostName + ", closing incident") -Verbose + $close_notes = ("Lockdown was already enabled on " + $VMHostName + " when checked, closing incident") + } + Else { + Write-Verbose -Message ("Lockdown successfully enabled on " + $VMHostName + ", closing incident") -Verbose + $close_notes = ("Lockdown successfully auto-enabled on " + $VMHostName); + } + Write-Verbose -Message ("Lockdown successfully enabled on " + $VMHostName + ", closing incident") -Verbose + Update-ITDServiceNowRecord -ItemType Incident -Number $Incident.number.display_value -Values @{ + close_code = 'Solved (Permanently)' + close_notes = $close_notes + u_underlying_cause = 'Configuration'; + state = 'Closed' + } + } + } + + Disconnect-ITDvCenter +} + +end { + +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTickets.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTickets.ps1 new file mode 100644 index 0000000..3002dbd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-LockdownTickets.ps1 @@ -0,0 +1,59 @@ + +<# +.SYNOPSIS + Checks VMware host lockdown mode status and creates incidents for disabled hosts. + +.DESCRIPTION + Recurring PSU schedule task, ~8am. + + This script connects to the ITD vCenter, retrieves all VMware hosts, and checks their lockdown mode status. + If lockdown mode is disabled on any hosts, it creates a ServiceNow incident for review. + +.EXAMPLE + .\VMware-LockdownTickets.ps1 + +.NOTES + Requires VMware PowerCLI and ITD ServiceNow modules. + Service account credentials must be available via $PrvCred and $Secret:ndgov_svcitdvmvcro. +#> +[CmdletBinding()] +param ( + +) + +begin { + +} + +process { + New-ITDServiceNowSession -Credential $Secret:snow_vmcred -Environment Production + Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro + + $AllVMHosts = Get-VMHost + $CurrentState = Get-ITDVMwareVMHostStatus -Name $AllVMHosts + $LockdownDisabled = $CurrentState | where-object lockdownmode -eq lockdowndisabled + + If ($LockdownDisabled) { + + ForEach ($VMHost in ($LockdownDisabled | Select -First 2)) { + Write-Verbose -Message "Start $($VMHost.Name) incident creation" + $NewIncidentParams = @{ + CallerUsername = 'svcvmwareadm'; + ShortDescription = ("Lockdown Mode is disabled on VMware host " + $VMHost.Name); + Description = ("Lockdown Mode is disabled on VMware host " + $VMHost.Name + ". Lockdown mode is a required for CIS hardening compliance 3.20 (L1)"); + Impact = 3; + Urgency = 1; + Category = 'Cloud Platforms' + Subcategory = 'Virtualization' + AssignmentGroup = 'NDIT-Cloud Platforms' + } + New-ITDServiceNowIncident @NewIncidentParams + } + } + + Disconnect-ITDvCenter +} + +end { + +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-NewVMWindows.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-NewVMWindows.ps1 new file mode 100644 index 0000000..a30f963 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-NewVMWindows.ps1 @@ -0,0 +1,982 @@ +#$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto +#$StdCred = $IaasAuto +#$PrvCred = $IaasAuto + +$FQDN = "itdzmtest001.nd.gov" +$CPU = 1 +$MemoryGB = 4 +$OS = "Windows Server 2019 Standard (64-Bit)" +$Environment = "Production" +$AppName = "Shared-PowerSchool" +$LicensingRestrictions = "Powerschool" +$VLAN = 1161 +$Datacenter = "Bismarck" + +Write-Warning "[$FQDN]:Start" +$SPCred = $StdCred +$ADCred = $IaasAuto +$PSCred = $PrvCred +$VMCred = $PrvCred +$CcmCred = $PrvCred +#$RadiusCred = $RadiusCred +$RadiusCred = New-Object System.Management.Automation.PSCredential($PrvCred.username.split('\')[1], ($PrvCred.Password)) + +Clear-DnsClientCache +$HostName = $FQDN.split('.')[0] + +# Infoblox +$InfobloxVlanMetadata = Get-ITDIbVlan -Vlan $VLAN -Credential $RadiusCred +$CIDR = $InfobloxVlanMetadata.AssignedTo +[Net.IpAddress]$NetworkId = $Cidr.split('/')[0] +[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress +$SubnetMaskInt = $CIDR.split('/')[1] +$Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) +[Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), + ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), + ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), + ([math]::Truncate($Int64 % 256)).ToString() +$IPSplit = $CIDR.Split('.') +[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) +<# + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Verbose "IP Address and CIDR Block match" + } + Else { + Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop + } + #> + +If ($IpAddress) { + If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { + Write-Warning "DNS record already exists, CIDR Block match" + } + else { + Write-Error "DNS record already exists, and does not match CIDR Block" + Break + } +} +Else { + New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred + [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress +} +#> +If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { + Write-Error "IP Address already in use." -ErrorAction Stop +} + +# Passwordstate BB before baseline, AB after baseline +If ($FQDN -like "itdcnd*") { + $PasswordStateList = "Peoplesoft Share PW" +} +Else { + $PasswordStateList = "CSRC" +} + + +# Passwordstate validation WIP +<#$ExistingPassword = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $PSCred -ErrorAction SilentlyContinue +If($ExistingPassword){ + $LocalCredential = $ExistingPassword +}#> + + + +$LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred +#$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) +#$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) +$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) +$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) +#$GuestCredential = $GuestCredentialBB + +# VMware +Connect-ITDvCenter -Credential $VMCred +If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) { + Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop + Stop + Stop +} + +switch ($LicensingRestrictions) { + "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" } + "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" } + "Microsoft SQL Enterprise" { $ClusterRoot = "SQL" } + "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "WINDOWS" } + "IBM Websphere" { $ClusterRoot = "WAS" } + "Powerschool" { $ClusterRoot = "PS" } + "Pexip" { $ClusterRoot = "TEL" } +} + +switch ($Datacenter) { + "Bismarck" { $ClusterInt = 1 } + "Mandan" { $ClusterInt = 2 } +} + +$Cluster = $ClusterRoot + $ClusterInt + +switch ($Cluster) { + "WINDOWS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL" + $DiskStorageFormat = 'EagerZeroThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "WINDOWS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WINDOWS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + If ($LicensingRestrictions -like "*SQL*") { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL" + $DiskStorageFormat = 'EagerZeroThick' + } + Else { + $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen" + $DiskStorageFormat = 'Thin' + } + } + "SQL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster SQL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen" + } + "SQL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster SQL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'EagerZeroedThick' + $DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen" + } + "WAS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster WAS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen" + } + "WAS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster WAS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen" + } + "PS1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster PS1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen" + } + "PS2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster PS2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen" + } + "TEL1" { + $ViServer = 'itdvmvc1.nd.gov' + $ComputeCluster = Get-Cluster TEL1 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen" + } + "TEL2" { + $ViServer = 'itdvmvc2.nd.gov' + $ComputeCluster = Get-Cluster TEL2 + $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data" + $DiskStorageFormat = 'Thin' + $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen" + } + Default { + Write-Error "Cluster not found" -ErrorAction Stop + } +} + +# verify disk will fit +$DiskTotal = 70 +If ($DatastoreCluster) { +} +Else { + $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $SPItem.Cluster + "*") +} +$ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1) +If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") +} +else { + Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)") + Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop +} + +$FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds" + +switch ($OS) { + "Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" } + "Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" } + "Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2019 Datacenter (64-Bit)" { $Template = "Windows Server 2019 Standard" } + "Windows Server 2022 Datacenter (64-Bit)" { $Template = "Windows Server 2022 Standard" } + Default { Write-Error "Invalid template" -ErrorAction Stop } +} + +$PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch +$PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $VLAN + "*") +If (!($PortGroup)) { + Write-Error "Virtual port group not found" -ErrorAction Stop + Stop +} +If (@($PortGroup).count -gt 1) { + Write-Error "Multiple port groups found" -ErrorAction Stop + Stop +} + +$NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S")) +Write-Warning "NewOSSpecName = $NewOSSpecName" +Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer + +Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Set-OSCustomizationSpec ` + -NamingScheme fixed ` + -NamingPrefix $Hostname ` + -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password + +Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | ` + Get-OSCustomizationNicMapping | ` + Set-OSCustomizationNicMapping ` + -IpMode UseStaticIP ` + -IpAddress $IpAddress.IPAddressToString ` + -SubnetMask $SubnetMask.IPAddressToString ` + -DefaultGateway $DefaultGateway.IPAddressToString ` + -Dns "10.2.7.40", "10.10.10.10" + +$OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer +<# + $NewVMParams = @{ + Name = $FQDN; + ResourcePool = $SPItem.Cluster; + Datastore = $DatastoreCluster; + DiskStorageFormat = $DiskStorageFormat; + Template = $Template; + Location = $FolderLocation; + OSCustomizationSpec = $OSSpec; + } + $NewVMParams + + New-VM @NewVMParams + #> + +#Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294 +# seems fixed on 2022/07/01 +try { + Write-Warning $FQDN + Write-Warning $ComputeCluster.Name + Write-Warning $DatastoreCluster + Write-Warning $DiskStorageFormat + Write-Warning $Template + Write-Warning $FolderLocation + Write-Warning $OSSpec + New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec +} +catch { + Stop + Stop +} + +#If (!($BuildError)) { +$VM = Get-VM -Name $FQDN + +# Ensure CPU/Memory Hot-Add Enabled +$vmView = $VM | Get-View +$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec +$vmOptValCPU = New-Object VMware.Vim.OptionValue +$vmOptValMem = New-Object VMware.Vim.OptionValue +$vmOptValCPU.Key = "vcpu.hotadd" +$vmOptValMem.Key = "mem.hotadd" +$vmOptValCPU.Value = "true" +$vmOptValMem.Value = "true" +$vmConfigSpec.ExtraConfig += $vmOptValCPU +$vmConfigSpec.ExtraConfig += $vmOptValMem +$vmView.ReconfigVM($vmConfigSpec) + +# Set CPU, Memory, Network +$VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false +$VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false + +# Power On VM +$VM | Start-VM + +# Wait for Customization to finish +$VMStarted = $false +$VMCustomizationStarted = $false +$VMCustomizationResult = $false + +While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) { + Write-Warning ("Customization wait loop started " + (Get-Date)) + Write-Verbose "Current Status:" + Write-Verbose ("VMStarted: " + $VMStarted) + Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted) + Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult) + $GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue } + Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds") + If ($VMStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) { + $VMStarted = $true + Write-Warning "[$FQDN]:Virtual machine started" + } + } + If ($VMCustomizationStarted -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) { + $VMCustomizationStarted = $true + Write-Warning "[$FQDN]:Virtual machine customization started" + } + } + If ($VMCustomizationResult -eq $false) { + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) { + $VMCustomizationResult = $true + Write-Error "[$FQDN]:Virtual machine customization failed" + Exit + Exit + } + If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) { + $VMCustomizationResult = $true + Write-Warning "[$FQDN]:Virtual machine customization completed" + } + } +} + +# Delete OS Customization Spec +# Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false + +# Add/Expand Disks +Write-Warning -Message "[$FQDN]:Modify disks 1,2,3" +$VMDisk = $VM | Get-HardDisk +$VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1" +$VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2" +$VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3" + + + $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1" + If ($VMDisk1.CapacityGB -lt 60) { + Set-HardDisk -HardDisk $VMDisk1 -CapacityGB 60 -Confirm:$false + } + + If (!$VMDisk2) { + $VM | New-HardDisk ` + -CapacityGB ($MemoryGB + 1) ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2" + If ($VMDisk2.CapacityGB -lt ($MemoryGB + 1)) { + Set-HardDisk -HardDisk $VMDisk2 -CapacityGB ($MemoryGB + 1) -Confirm:$false + } + + If (!$VMDisk3) { + $VM | New-HardDisk ` + -CapacityGB 20 ` + -StorageFormat Thin ` + -DiskType Flat ` + -Persistence Persistent + } + $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3" + If ($VMDisk3.CapacityGB -lt 20) { + Set-HardDisk -HardDisk $VMDisk3 -CapacityGB 20 -Confirm:$false + } + +# skipping tag assignment for now +# Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose + +# Run Guest OS code +# Enable RDP with NLA - can be done with GPO +# Enable WinRM - ITD WinRM enable +# Configure Power Plan - ITD-PowerPlan-HighPerformance +# Activate Windows, KMS on-premise, Azure to Azure +# DVD Drive to Z: +# Expand C: +# Partition/Format the rest, GPT/NTFS +# Configure Page File Disk +# Enabling server manager performance monitors +# Configure Time Zone and NTP - no GPO available +# Disable Windows Firewall +# Join AD + +#Initialize-ITDServer -Credential $ADCred + + +Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + Write-Verbose "Create new Class" + $Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null); + + $Class["__CLASS"] = "ITD"; + $Class.Qualifiers.Add("Static", $true) + $Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false) + $Class.Properties["MyKey"].Qualifiers.Add("Key", $true) + + $Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false) + $Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false) + $Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false) + + $Class.Put() + + Write-Verbose "Create single ITD Object" + Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" } + } + catch { + Throw $_ + Break + } +} + +Write-Warning -Message "[$FQDN]:Checking for DVD drive..." +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Move DVD Drive Mount + try { + $dvd_letter = 'Z' + $dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1 + if ($dvd.Name -notmatch $dvd_letter) { + Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:" + + Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null + + Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:" + } + else { + Write-Verbose -Message "No DVD drive changes required, continuing..." + } + } + catch { + Throw $_ + Break + } +} + +Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..." +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Expand C: Partition To Maximum Extent + + + try { + $cSize = ( Get-Partition -DriveLetter C ).Size + $cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax + + if ($cSize -lt $cMaxSize) { + Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..." + + Resize-Partition -DriveLetter C -Size $cMaxSize + + Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB." + } + else { + Write-Verbose -Message "C: is already at maximum size, continuing..." + } + } + catch { + Throw $_ + Break + } +} + +Write-Warning "[$FQDN]:Start Extra Disk(s) config" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Initialize Additional Disks + try { + # Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default + $disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number + + if ($disks) { + Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks." + + # Prevent the "You must format this partition before using it." popup + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue } + + foreach ($disk in $disks) { + if ($disk.IsOffline) { + Set-Disk $disk.Number -IsOffline $false + Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..." + } + + if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false } + if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue } + + $diskParam = @{ + FileSystem = 'NTFS' + Confirm = $false + } + + $driveLetter = [Int][Char]'D' + while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) { + $driveLetter++ + } + + $diskParam.DriveLetter = [Char]$driveLetter + + if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Temporary Storage' + } + elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) { + $diskParam.NewFileSystemLabel = 'Data' + } + + [void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize) + [void](Format-Volume @diskParam) + } + } + else { + Write-Verbose -Message "No unpartitioned disks found, continuing..." + } + } + catch { + Throw $_ + Break + } + finally { + if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue } + } +} + +Write-Warning "[$FQDN]:Start Page File Configuration" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Page File + if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Setting up pagefile.sys on D:..." + + try { + if (-not [IO.File]::Exists('D:\pagefile.sys')) { + $autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges + $autoPage.AutomaticManagedPagefile = $false + [void]$autoPage.Put() + + Write-Verbose -Message "Disabled automatic pagefile management." + + $pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges + $pageFile.Delete() + + Write-Verbose -Message "Deleted C:\pagefile.sys." + + Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null + + Write-Verbose -Message "System managed page file created on D:\pagefile.sys." + } + else { + Write-Verbose -Message "Pagefile already configured on D:, continuing..." + } + } + catch { + Throw $_ + Break + } + } + else { + Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..." + Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..." + } +} + +Write-Warning -Message "[$FQDN]:Enabling Remote Management..." +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Remote Management (RDP/PoSH) + try { + Write-Verbose -Message "Checking WinRM..." + + if (Test-WSMan -ErrorAction SilentlyContinue) { + Write-Verbose -Message "WinRM is already enabled." + } + else { + Enable-PSRemoting -Force + + Write-Verbose -Message "WinRM is now enabled." + } + + Write-Verbose -Message "Checking RDP..." + + $RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices + $NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'" + if ($RDP.AllowTSConnections -eq 0) { + Write-Verbose -Message "RDP is disabled, enabling..." + + $RDP.SetAllowTSConnections(1, 1) | Out-Null + + Write-Verbose -Message "RDP is enabled." + } + else { + Write-Verbose -Message "RDP is already enabled, checking NLA security..." + } + + if ($NLA.UserAuthenticationRequired -eq 0) { + Write-Verbose -Message "RDP is not NLA secured, enabling..." + + $NLA.SetUserAuthenticationRequired(1) | Out-Null + + Write-Verbose -Message "RDP is now NLA secured." + } + else { + Write-Verbose -Message "RDP is already NLA secured." + } + + } + catch { + Throw $_ + Break + } +} + +Write-Warning -Message "[$FQDN]:Checking current power plan..." +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Configure Power Plan + try { + $powerPlans = powercfg -l + + if ($powerPlans -match '\*$' -notmatch 'High performance') { + $currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value + + Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..." + + $highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value + [void](powercfg -setactive $highPerformance) + + Write-Verbose -Message "Power plan set to High Performance." + } + else { + Write-Verbose -Message "Power plan already configured for High Performance." + } + + [void](& w32tm.exe /resync /nowait) + } + catch { + Throw $_ + Break + } +} + + +$TimeSyncFunc = { + # Configure Time/Date Settings + Write-Verbose -Message "Checking current time/date settings..." + $Domain = "" + try { + if ((Get-TimeZone).Id -ne 'Central Standard Time') { + Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time." + + Set-TimeZone -Id 'Central Standard Time' + + Write-Verbose -Message "Time zone set to Central Standard Time." + } + else { + Write-Verbose -Message "Time zone is already set to Central Standard Time." + } + <# + Write-Verbose -Message "Beginning a time synchronization..." + + if ((Get-Service W32Time).Status -eq 'Stopped') { + Start-Service W32Time + } + + [void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update) + + [void](& w32tm.exe /resync /nowait) + + # Start background job to check time service + $tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock { + do { + $tmOut = & w32tm.exe /query /status /verbose + + Start-Sleep -Seconds 10 + } until($tmOut -match '^Last Sync Error: 0\D+$') + } + + # If after three minutes time still has not synched, move on. This usually causes no problems. + if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') { + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful." + } + else { + [void](Stop-Job -Job $tmJob) + Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed." + } + #> + } + catch { + Throw $_ + Break + } +} +$TimeSyncScriptBlock = $TimeSyncFunc -replace '', $DomainName +$VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock +#> +Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..." +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Enable Performance Counters + + + try { + if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) { + Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask + + Write-Verbose -Message "Performance monitors enabled." + } + else { + Write-Verbose -Message "Performance monitors already enabled, continuing..." + } + } + catch { + Throw $_ + Break + } +} + +Write-Warning -Message "[$FQDN]:Disable Windows Firewall" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText { + # Disable Windows Firewall + Write-Verbose -Message "Checking for active Windows Firewall..." + + if ((Get-NetFirewallProfile).Enabled -contains 'True') { + Write-Verbose -Message "Windows Firewall is still enabled, disabling it..." + + Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False + + Write-Verbose -Message "Windows Firewall disabled." + } + else { + Write-Verbose -Message "Windows Firewall already disabled, continuing..." + } +} + +# Active Directory +Write-Warning "[$FQDN]:Join Active Directory (if required)" +$DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) +switch ($DomainName) { + 'nd.gov' { + $SearchBaseDomain = "dc=nd,dc=gov" + } + 'ndcloud.gov' { + $SearchBaseDomain = "dc=ndcloud,dc=gov" + } +} + +If ($DomainName -eq "nd.gov") { + $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter {Name -eq $AppName} + If (!($OUAppName)) { + $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } + } + $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } + If ($ExistingADComputer) { + If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { + Write-Warning "AD object already exists, OU path does match" + $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? -OUPath "" -Credential $DomainJoinCred' + $SecondScriptText = $SecondScriptText -replace '', $DomainName + $SecondScriptText = $SecondScriptText -replace '', $OuFinal + $SecondScriptText = $SecondScriptText -replace '', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) + + Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join" + $InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText") + + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc + + Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after" + Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false + Wait-Tools -VM (Get-VM -Name $FQDN) + Start-Sleep -Seconds 90 +} + +Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date)) +Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force +Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date)) +#E:\AutoBuild\SCCM_Client\ + +# Check if SCCM automatically installed the SCCM client and registered it +$CcmRegistered = $false +$CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log +} +If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true +} +ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true +} +If ($CcmRegistered -eq $false) { + Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + + If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installing" + $CcmRegistered = $true + } + ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) { + Write-Warning "CCM client is already installed" + $CcmRegistered = $true + } + Else { + Write-Warning -Message "Installing SCCM Client..." + Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov" + } + } +} + +Write-Warning "[$FQDN]:Register SCCM Client" +While ($CcmRegistered -eq $false) { + $CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log + } + If ($CcmRegistration.ScriptOutput -match "Client is registered") { + Write-Warning "Client is registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") { + Write-Warning "Client is already registered." + $CcmRegistered = $true + } + ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 } +} + +Write-Warning -Message "[$FQDN]:Approve SCCM Client" +#Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL +Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock { + Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' + $PSDrives = Get-PSDrive + If ($PSDrives | Where-Object Name -EQ "ITD") { + # ITD Drive exists, do nothing + } + else { + New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov + } + + Set-Location ITD:\ + $Device = Get-CMDevice -Name $args[0] + If ($Device.IsApproved -eq 0) { + Approve-CMDevice -DeviceName $args[0] + } +} + +# vcenter tags +#AppName Tag + +New-TagAssignment -Entity (Get-VM $FQDN -server $VIServer) -Tag (Get-Tag -Server $VIServer -Category AppName -Name $AppName) -Server $VIServer +New-TagAssignment -Entity (Get-VM $FQDN -server $VIServer) -Tag (Get-Tag -Server $VIServer -Category DTAP -Name $Environment) -Server $VIServer + + +Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); +} + +Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy" +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); +} +#Start-Sleep -Seconds 180 + +Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...' +Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText { + # Pause until network connectivity is available + + $KMS = 'kms.nd.gov' + + try { + $nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock { + Param ( [String]$KMS ) + do { + $nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet + + Start-Sleep -Seconds 10 + } until($nwStatus) + } -ArgumentList $KMS + + # If after 30 seconds the network connection is not responding continue on + if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') { + Write-Verbose -Message 'Network connectivity has been verified.' + } + else { + [void](Stop-Job -Job $nwJob) + Write-Verbose -Message 'Network connectivity could not be verified.' + } + } + catch { + Throw $_ + Break + } + + # Activate via KMS + Write-Verbose -Message "Activating windows against $KMS..." + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit + } + try { + cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null + cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null + + Write-Verbose -Message "Checking activation status..." + + $kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli + + if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') { + Write-Verbose -Message "Windows successfully activated." + } + else { + Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct." + } + } + catch { + Throw $_ + Break + } +} +Write-Warning "[$FQDN]:End" + + +<# +Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { Get-Process -Name ccmexec*, cohesity*, cyserver*, nessus*, vmtoolsd* } + +Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in" +Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { + [void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}"); +}#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagBladeLocation.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagBladeLocation.ps1 new file mode 100644 index 0000000..d525bbd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagBladeLocation.ps1 @@ -0,0 +1,18 @@ +$OVServers = Get-OVServer + +ForEach($OVServer in $OVServers){ + $Enclosure = $OVServer.Name.split('_')[0] + $VMHost = Get-VMHost -Name $OVServer.ServerName + $ViServer = $VMHost.Uid.Split("@")[1].Split(':')[0] + $OldTagAssignment = $VMhost | Get-TagAssignment + $OldTag = $OldTagAssignment.Tag + $NewTag = Get-Tag -Category "HPE Enclosure" -Name $Enclosure -Server $ViServer + + If ($OldTag -eq $NewTag){ + + } + Else{ + $OldTagAssignment | Remove-TagAssignment -Confirm:$false + $VMHost | New-TagAssignment -Tag $NewTag + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagVMs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagVMs.ps1 new file mode 100644 index 0000000..ff23fc7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-TagVMs.ps1 @@ -0,0 +1,245 @@ +function Set-ITDVMwareVMTag { + [CmdletBinding()] + param + ( + [string] + $ComputerName, + + [string] + $AppName, + + [string] + $Dtap, + + [string] + $OperatingSystem, + + [string] + $StartupPriority + ) + + begin { + } + + process { + + $VMs = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If ($VMs) { + ForEach ($VM in $VMs) { + #AppName Tag + Write-Verbose ($VM.Name + ": AppName Tag Start") + $OldTag = Get-TagAssignment -Category AppName -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $AppName + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " AppName old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category AppName -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer)# + } + Write-Verbose ($VM.Name + ": AppName Tag End") + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + #DTAP Tag + Write-Verbose ($VM.Name + ": DTAP Tag Start") + $OldTag = Get-TagAssignment -Category DTAP -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $DTAP + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " DTAP old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category DTAP -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + Write-Verbose ($VM.Name + ": DTAP Tag End") + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + #Startup Priority + Write-Verbose ($VM.Name + ": StartupPriority Tag Start") + $OldTag = Get-TagAssignment -Category 'StartupPriority' -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $StartupPriority + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " StartupPriority old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'StartupPriority' -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + Write-Verbose ($VM.Name + ": StartupPriority Tag End") + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + # OS Tag + Write-Verbose ($VM.Name + ": OS Tag Start") + $OldTag = Get-TagAssignment -Category "Operating System" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $OperatingSystem + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " OS old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'Operating System' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + Write-Verbose ($VM.Name + ": OS Tag End") + + # Licensing Tag + Write-Verbose ($VM.Name + ": Licensing Restrictions Tag Start") + $OldTag = Get-TagAssignment -Category "LicensingRestrictions" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $LicensingRestrictions + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " Licensing old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'LicensingRestrictions' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + Write-Verbose ($VM.Name + ": Licensing Tag End") + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + + <# SRM Recovery Type Tags + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag Start") + $OldTag = Get-TagAssignment -Category "SRM Recovery Type" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + If ($VM.ExtensionData.summary.config.ManagedBy.Type -eq "placeholderVm" ) { + #If VM is placeholder + $NewTagName = "Placeholder" + } + Else { + $NewTagName = $SPItem.SRM_RecoveryVMtype + } + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " SRM Recovery Type old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'SRM Recovery Type' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag End")#> + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + <#VR RPO Tag + Write-Verbose ($VM.Name + ": SRM Tag Start") + $OldTag = Get-TagAssignment -Category 'VR RPO' -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $SPItem.DR_Protection -replace "VMware: " + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " SRM old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'VR RPO' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + + }#> + } + } + Else { + + } + #} + <#catch { + Write-Error ($VM.Name + " tag errored") + Write-Error $error[-1] + }#> + + + } + + end { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMCpuMemoryClusterSRMReport.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMCpuMemoryClusterSRMReport.ps1 new file mode 100644 index 0000000..54a0043 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMCpuMemoryClusterSRMReport.ps1 @@ -0,0 +1,3 @@ +$AllVMs = Get-Datacenter -Name Primary* | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "vCLS*" } + +$AllVMs | Select Name,NumCpu,MemoryGB,@{n='Cluster';e={$_.VMHost | Get-Cluster}},@{n='SRM Recovery Type';e={($_ | Get-TagAssignment -Category "SRM Recovery Type").Tag.Name}} -OutVariable result \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMDailyMetadataReport_Csv.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMDailyMetadataReport_Csv.ps1 new file mode 100644 index 0000000..a2daf2d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMDailyMetadataReport_Csv.ps1 @@ -0,0 +1,177 @@ +<# +.SYNOPSIS + Daily VM metadata report for PowerBI trending and hardware capacity planning. + +.DESCRIPTION + Collects VM metadata from vCenter including compute, storage, OS, and VMware Tools + information using only data available within vCenter (no direct guest connections). + Exports a timestamped CSV each run -- append daily runs to build a historical dataset + suitable for PowerBI trend analysis and physical hardware purchasing decisions. + +.PARAMETER vCenterServers + One or more vCenter server hostnames. Defaults to itdvmvc1.nd.gov and itdvmvc2.nd.gov. + +.PARAMETER DatacenterFilter + Wildcard filter applied to datacenter names. Defaults to 'Primary*'. + +.PARAMETER OutputPath + Directory where CSV and log files are written. + Defaults to C:\ITDSCRIPT\Reports\VMMetadata. + +.PARAMETER CredentialPath + Path to a saved PSCredential XML file for unattended/scheduled runs. + Create one interactively with: + Get-Credential | Export-Clixml -Path C:\ITDSCRIPT\Creds\vCenter.xml + When omitted the script prompts for credentials. + +.EXAMPLE + # Interactive run + .\VMware-VMDailyMetadataReport.ps1 + +.EXAMPLE + # Scheduled / unattended run + .\VMware-VMDailyMetadataReport.ps1 -CredentialPath 'C:\ITDSCRIPT\Creds\vCenter.xml' + +.NOTES + Scheduled Task suggestion (run as service account that owns the credential XML): + Program : powershell.exe + Args : -NonInteractive -ExecutionPolicy Bypass -File "C:\ITDSCRIPT\VMware-VMDailyMetadataReport.ps1" -CredentialPath "C:\ITDSCRIPT\Creds\vCenter.xml" + Trigger : Daily at 06:00 + + Guest OS disk capacity / used columns are populated only for powered-on VMs with + VMware Tools running; they will be empty for powered-off VMs and SRM placeholders. +#> +[CmdletBinding()] +param( + [string] $OutputPath = 'C:\temp\VM_Trends\' +) + +#region --- Setup --------------------------------------------------------------- + +$RunDate = Get-Date +$DateStamp = $RunDate.ToString('yyyyMMdd') +$Timestamp = $RunDate.ToString('yyyy-MM-dd HH:mm:ss') + +if (-not (Test-Path -Path $OutputPath)) { + New-Item -ItemType Directory -Path $OutputPath | Out-Null +} + +Start-Transcript -Path (Join-Path $OutputPath "VMMetadataReport_$DateStamp.log") -Append + +#endregion + +#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-VM API calls) - + +Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...' +$HostClusterMap = @{} +$HostDatacenterMap = @{} + +Get-Datacenter | ForEach-Object { + $DatacenterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostDatacenterMap[$_.Name] = $DatacenterName + } +} + +Get-Cluster | ForEach-Object { + $ClusterName = $_.Name + Get-VMHost -Location $_ | ForEach-Object { + $HostClusterMap[$_.Name] = $ClusterName + } +} + +#endregion + +#region --- Collect VM Data ----------------------------------------------------- + +Write-Verbose "Gathering VMs" + +# Include ALL VMs (SRM placeholders flagged via column, not excluded). +# vCLS agent VMs are excluded -- they are vSphere internal and not customer workloads. +$AllVMs = Get-VM | Where-Object { $_.Name -notlike 'vCLS*' } + +Write-Verbose "Processing $($AllVMs.Count) VMs..." + +$Results = foreach ($VM in $AllVMs) { + + $Ext = $VM.ExtensionData # single API object -- reuse for all fields + + #--- SRM placeholder detection + $IsSRMPlaceholder = $Ext.Summary.Config.ManagedBy.Type -eq 'placeholderVm' + + #--- Cluster / Datacenter (null-safe: standalone hosts have no cluster entry) + $ClusterName = $HostClusterMap[$VM.VMHost.Name] + $DatacenterName = $HostDatacenterMap[$VM.VMHost.Name] + + #--- Storage platform parsed from datastore name convention: VMCLUSTER_LUN_PLATFORM_Desc + # Segment 2 = storage platform identifier (e.g. FS92, A9K). + # Cluster grouping uses the compute Cluster column -- no need to re-derive it here. + $StoragePlatforms = foreach ($DSName in $Ext.Config.DatastoreUrl.Name) { + $Segments = $DSName -split '_' + if ($Segments.Count -ge 3) { $Segments[2] } + } + $StoragePlatform = ($StoragePlatforms | Sort-Object -Unique) -join '; ' + + #--- VMware Tools guest disk info + # Populated only when Tools is running; null otherwise. + $GuestDiskCapacityGB = $null + $GuestDiskUsedGB = $null + if ($Ext.Guest.Disk) { + $TotalCapBytes = ($Ext.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum + $TotalFreeBytes = ($Ext.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum + $GuestDiskCapacityGB = [Math]::Round($TotalCapBytes / 1GB, 2) + $GuestDiskUsedGB = [Math]::Round(($TotalCapBytes - $TotalFreeBytes) / 1GB, 2) + } + + [PSCustomObject]@{ + # --- Identity & grouping + ReportDate = $Timestamp # for PowerBI time-series/trend axis + VMName = $VM.Name + Datacenter = $DatacenterName + Cluster = $ClusterName + PowerState = $VM.PowerState + IsSRMPlaceholder = $IsSRMPlaceholder + StoragePlatform = $StoragePlatform + GuestOS = $Ext.Guest.GuestFullName + + # --- Compute + vCPUs = $VM.NumCpu + MemoryGB = $VM.MemoryGB + + # --- Datastore-level storage + # ProvisionedSpaceGB : maximum the VM could consume (thin disks counted at max size) + # UsedSpaceGB : bytes actually committed on datastores right now + ProvisionedSpaceGB = [Math]::Round($VM.ProvisionedSpaceGB, 2) + UsedSpaceGB = [Math]::Round($VM.UsedSpaceGB, 2) + + # --- Guest OS-level storage (from VMware Tools; null when Tools not running) + # GuestDiskCapacityGB : sum of all volume capacities seen inside the guest + # GuestDiskUsedGB : sum of space consumed across those volumes + GuestDiskCapacityGB = $GuestDiskCapacityGB + GuestDiskUsedGB = $GuestDiskUsedGB + + # --- VMware Tools + # ToolsRunningStatus : guestToolsRunning | guestToolsNotRunning | guestToolsExecutingScripts + # ToolsVersionStatus : guestToolsCurrent | guestToolsNeedUpgrade | guestToolsUnmanaged | guestToolsTooNew + # ToolsVersion : numeric build version string reported by vCenter + ToolsRunningStatus = $Ext.Guest.ToolsRunningStatus + ToolsVersionStatus = $Ext.Guest.ToolsVersionStatus + ToolsVersion = $Ext.Guest.ToolsVersion + } +} + +#endregion + +#region --- Export -------------------------------------------------------------- + +$OutputFile = Join-Path $OutputPath "VMMetadata_$DateStamp.csv" +$Results | Export-Csv -Path $OutputFile -NoTypeInformation + +Write-Verbose "Exported $($Results.Count) VM records to: $OutputFile" + +#endregion + +#region --- Cleanup ------------------------------------------------------------- +Stop-Transcript + +#endregion diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBoot.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBoot.ps1 new file mode 100644 index 0000000..3de307e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBoot.ps1 @@ -0,0 +1,42 @@ +# report current status +$AllVMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } +$WS2022VMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestFullName -like "*2022*" } | Sort-Object Name +$WS2022VMs | select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } } + + + +$VMNames = @" +itdexchtest1.testnd.gov +itdexchtest2.testnd.gov +itdexch1.nd.gov +itdexch2.nd.gov +"@ + +$VMNames = ConvertTo-Array -MultiLineString $VMNames + +# power off VMs +ForEach ($VMName in $VMNames) { + Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Stop-VMGuest -Confirm:$false +} + +# wait for all to be powered off +Get-VM -Name $VMNames + +# disable secure boot on all of them +ForEach ($VMname in $VMNames) { + $vm = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + $spec = New-Object VMware.Vim.VirtualMachineConfigSpec + $spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi + $boot = New-Object VMware.Vim.VirtualMachineBootOptions + $boot.EfiSecureBootEnabled = $false # false to disable obviously + $spec.BootOptions = $boot + $vm.ExtensionData.ReconfigVM($spec) +} + +# validate +Get-VM -Name $VMNames | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }| select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } } + +# power on +ForEach($VMName in $VMNames){ + Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Start-VM +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBootB.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBootB.ps1 new file mode 100644 index 0000000..877561a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-VMSecureBootB.ps1 @@ -0,0 +1,42 @@ +# report current status +$AllVMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } +$WS2022VMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestFullName -like "*2022*" } | Sort-Object Name +$WS2022VMs | select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } } + + + +$VMNames = @" +itdaddressprot2.nd.gov +itdqlikreptst1.ndcloud.gov +itdqlikrepprd1.ndcloud.gov +itdexch1.nd.gov +itdexch2.nd.gov +itdexchtest1.testnd.gov +itdexchtest2.testnd.gov +"@ + +$VMNames = ConvertTo-Array -MultiLineString $VMNames + +# power off VMs +ForEach ($VMName in $VMNames) { + Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Stop-VMGuest -Confirm:$false +} + +# wait for all to be powered off +Get-VM -Name $VMNames + +# disable secure boot on all of them +ForEach ($VMname in $VMNames) { + $vm = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + $spec = New-Object VMware.Vim.VirtualMachineConfigSpec + $spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi + $boot = New-Object VMware.Vim.VirtualMachineBootOptions + $boot.EfiSecureBootEnabled = $true # false to disable obviously + $spec.BootOptions = $boot + $vm.ExtensionData.ReconfigVM($spec) +} + +# power on +ForEach($VMName in $VMNames){ + Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Start-VM +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-vCenterUpgrade.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-vCenterUpgrade.ps1 new file mode 100644 index 0000000..4affb9c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/VMware-vCenterUpgrade.ps1 @@ -0,0 +1,71 @@ +# Dump list of VMs from ServiceNow +Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "serial_numberSTARTSWITHvmware" -IncludeTotalCount | Export-Csv "C:\temp\CMDB_VMwareDump.csv" + +# Disable DRS on all clusters +Get-Cluster LINUX*, MGMT*, ORACLE1, PS*, SQLa*, SQLe*, VAPP*, WAS*, WINDOWS* | Set-Cluster -DrsEnabled $false + +# Dump location of all VMs to CSV +Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } | select Name, PowerState, NumCpu, MemoryGB, VMHost, @{n = 'Datastores'; e = { ($_ | Get-Datastore).Name } } | Export-Csv "D:\State of North Dakota\-Tm-ITD-Virtualization - Documents\VMinfo.csv" + +# VM array +$VMHosts = @( + 'itdvmbismgmt02.nd.gov', + 'itdvmbismgmt03.nd.gov', + 'itdvmmdnmgmt01.nd.gov', + 'itdvmbismgmt02.nd.gov' +) + +# Disable lockdown on MGMT hosts +$VMHosts | ForEach-Object { + (Get-VMHost -Name $_ | Get-View).ExitLockdownMode() +} + +# connect to mgmt cluster +$VMHosts | ForEach-Object { + Connect-VIServer -Server $_ -Credential (Get-ITDPassword -Title $_ -UserName root -Credential $PrvCred) +} + +## verify lockdown mode is disabled manually + +# get list of VMs | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } +$VMs = Get-VM | Where-Object { $_.Name -notlike "vCLS*" -and $_.PowerState -eq "PoweredOn" -and $_.Name -notlike "itdvmutil*" -and $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm"} | Sort-Object Name + +# Cleanup snapshots on MGMT cluster +$VMs | Get-Snapshot | Where-Object Name -NotLike "*9.0.2*" | Remove-Snapshot -RunAsync + +# Shutdown all appliance VMs on MGMT cluster +$VMs | Stop-VMGuest -Confirm:$false #-RunAsync + +# Wait for VMs to power off +Get-VM -Name $VMs.Name | Sort-Object Name +#Get-Cluster MGMT1, MGMT2 | Get-VM | Where-Object { $_.Name -notlike "itdvmutil*" } | Sort-Object Name + +# Create offline snapshots +$VMs | New-Snapshot -Name "9_Before 8.0 U3e Upgrade" -Description "9_Before 8.0 U3e Upgrade" -Confirm:$false -RunAsync + +# Power on all VMs on MGMT cluster +$VMs | Start-VM -Confirm:$false + +Break + +## online mid-upgrade snapshots +$VMs | New-Snapshot -Name "1_vc_upgrade_complete" -Description "2_vc1_stage2_complete" -Confirm:$false -RunAsync -Memory + +Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | Where-Object {$_.Name -notlike "*7.0*"} | Stop-VMGuest -Confirm:$false + +# post upgrade snapshot +Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | New-Snapshot -Name "2_vc_upgrade_complete" -Description "2_vc1_stage2_complete" -Confirm:$false -RunAsync -Memory +Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | Start-VM +##### after upgrade + +# Enable DRS on clusters that should have it +Get-Cluster LINUX*, MGMT*, ORACLE1, PS*, SQLa*, SQLe*, VAPP*, WAS*, WINDOWS* | Set-Cluster -DrsEnabled $true + +# Enable lockdown on MGMT hosts +(Get-VMHost itdvmbismgmt01.nd.gov | Get-View).EnterLockdownMode() +(Get-VMHost itdvmbismgmt02.nd.gov | Get-View).EnterLockdownMode() +(Get-VMHost itdvmmdnmgmt01.nd.gov | Get-View).EnterLockdownMode() +(Get-VMHost itdvmmdnmgmt02.nd.gov | Get-View).EnterLockdownMode() + +# reconfigure distributed switch to use both vnics +#### manual \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/vCenterUpgrade.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/vCenterUpgrade.ps1 new file mode 100644 index 0000000..cfa39b8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Scripts/vCenterUpgrade.ps1 @@ -0,0 +1,13 @@ +$AllVMs = Get-VM | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +$data = $AllVMs | ` + Select-Object Name, ` + VMHost, ` + UsedSpaceGB, ` + ProvisionedSpaceGB #, ` + #@{n = 'Disks'; e = { $_ | Get-HardDisk | Select Name, FileName, CapacityGB } }, ` + #@{n = 'VRDatastore'; e = { ($_ | Get-TagAssignment | Where-Object Tag -like "*_VR").Tag } } ` + #@{n = 'PortGroups'; e = { $_ | Get-VirtualPortGroup } } + +$data | export-csv "C:\users\zmeier\desktop\VMs_20200122.csv" + +get-vm itdvmpsc1*,itdvmvc1*,itdvmpsc2*,itdvmvc2* | new-snapshot -name "VC1-6.7 U3-Stage1 Complete" \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/CompareVMSRMList-Task.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/CompareVMSRMList-Task.ps1 new file mode 100644 index 0000000..e78971a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/CompareVMSRMList-Task.ps1 @@ -0,0 +1,8 @@ +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "D:\PowerShellTasks\CompareVMSRMList\Logs\CompareVMSRMList-$Timestamp.log" +Start-Transcript $TranscriptPath + +$result = Compare-ITDVMwareVMSRMList -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose +$body = "" + ($result | ConvertTo-Html) + +Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Body $body -SmtpServer apprelay1.nd.gov -BodyAsHtml -Subject "VMware SRM conflicts" -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetAzureVMGuestIPsForPA.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetAzureVMGuestIPsForPA.ps1 new file mode 100644 index 0000000..92ddc68 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetAzureVMGuestIPsForPA.ps1 @@ -0,0 +1,146 @@ +<# Scheduled Task metadata +General + GetAzureVMGuestIPsForPA + run as ndgov\svcitdiaasauto + run whether user is logged on or not + Triggers + Daily, 2pm - repeat every 1 hour indefinitely +Actions + "C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetAzureVMGuestIPsForPA\GetAzureVMGuestIPsForPA.ps1" +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + + + +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" +Start-Transcript F:\GetAzureVMGuestIPsForPA\Logs\GetAzureVMGuestIPsForPA-$Timestamp.log +$VerbosePerfrence = "Continue" + +#[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$OutputPath = "C:\inetpub\wwwroot" + +$WindowsIPs = "" +$LinuxIPs = "" +$OutFileWin = $OutputPath + "\AzureWin.txt" +$OutFileLin = $OutputPath + "\AzureLin.txt" +Remove-Item $OutFileWin +Remove-Item $OutFileLin + +$WindowsIpArray = [string]@() +$LinuxIpArray = [string]@() + +# replace with PowerShell.SecretManagement +#$username="svcitdazurescript@nd.gov" +#$usernameg="svcitdazurescript@ndstate.onmicrosoft.com" +#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat +#$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString +#$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString +#$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password +#$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg + +# Prepare credentials +$svcitdazurescript = Get-Secret -Name svcitdazurescript +$MacCred = New-Object System.Management.Automation.PSCredential("svcitdazurescript@nd.gov", $svcitdazurescript.Password) +# no VMs or PAs in AzureGov yet (2023/09/26) $MagCred = Get-Secret -Name svcitdazurescriptgov + +# Azure Commercial +$AzAccount = Connect-AzAccount -Credential $MacCred -Environment AzureCloud -Verbose +$Subscriptions = Get-AzSubscription | Where-Object { $_.Name -ne "sandbox" -and $_.Name -notlike "Visual Studio*" -and $_.Name -notlike "Azure subscription*" -and $_.Name -notlike "Access to Azure Active Directory*"} +foreach ($subscription in $subscriptions) { + Set-AzContext -Subscription $subscription + $WindowsVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Windows" } + $LinuxVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks" } + $nics = Get-AzNetworkInterface | Where-Object { $_.VirtualMachine -NE $null } + + foreach ($vm in $WindowsVMs) { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach ($vmnicinterface in $vmnicinterfaces) { + $nic = $nics | Where-Object { $_.Id -eq $vmnicinterface } + $privateip = $nic.IpConfigurations | select PrivateIPAddress + + If ($privateip.count -gt 1) { + foreach ($private in $privateip) { + Write-Warning -Message ($VM.Name + "zzzzz") + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf ($privateip.privateIPAddress -ne $null) { + Write-Warning -Message ($VM.Name + "xxxxx") + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach ($vm in $LinuxVMs) { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach ($vmnicinterface in $vmnicinterfaces) { + $nic = $nics | Where-Object { $_.Id -eq $vmnicinterface } + $privateip = $nic.IpConfigurations | select PrivateIPAddress + + If ($privateip.count -gt 1) { + foreach ($private in $privateip) { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif ($privateip.privateIPAddress -ne $null) { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} + + +#Azure Gov +<# no VMs or PAs in AzureGov yet (2023/09/26) +$AzAccount = Connect-AzAccount -Credential $MagCred -Environment AzureUSGovernment -Verbose + +$Subscriptions = Get-AzureRMSubscription | Where-Object { $_.Name -ne "sandbox" } +foreach ($subscription in $subscriptions) { + Set-AzContext -Subscription $subscription + $WindowsVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Windows" } + $LinuxVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks" } + $nics = Get-AzNetworkInterface | Where-Object { $_.VirtualMachine -NE $null } + + foreach ($vm in $WindowsVMs) { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach ($vmnicinterface in $vmnicinterfaces) { + $nic = $nics | Where-Object { $_.Id -eq $vmnicinterface } + $privateip = $nic.IpConfigurations | select PrivateIPAddress + + If ($privateip.count -gt 1) { + foreach ($private in $privateip) { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf ($privateip.privateIPAddress -ne $null) { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach ($vm in $LinuxVMs) { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach ($vmnicinterface in $vmnicinterfaces) { + $nic = $nics | Where-Object { $_.Id -eq $vmnicinterface } + $privateip = $nic.IpConfigurations | select PrivateIPAddress + + If ($privateip.count -gt 1) { + foreach ($private in $privateip) { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif ($privateip.privateIPAddress -ne $null) { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} +#> +#If ($WindowsIPs -ne "" -and $WindowsIPs.Length -gt 150) { $WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force } +#If ($LinuxIPs -ne "" -and $LinuxIPs.Length -gt 150) { $LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force } + +$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force +$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetVMwareVMGuestIPsForPA.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetVMwareVMGuestIPsForPA.ps1 new file mode 100644 index 0000000..1ee1af0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/GetVMwareVMGuestIPsForPA.ps1 @@ -0,0 +1,122 @@ + <# Scheduled Task metadata + General + Get IPs for PA + run as ndgov\!itdvcenterppa + run whether user is logged on or not + Triggers + Daily, 11am + Daily, 11pm + Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1" + new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetVMwareVMGuestIPsForPA\GetVMwareVMGuestIPsForPA.ps1" + + Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop + #> + + $TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" + Start-Transcript F:\GetVMwareVMGuestIPsForPA\Logs\GetVMwareVMGuestIPsForPA-$Timestamp.log + #Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false + #Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false + + #Connect + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov + + + ##Windows + + + #Output File + $OutFileWin = "c:\inetpub\wwwroot\Win.txt" + #$Date = Get-Date -UFormat "%Y%m%d%H%M%S" + Get-Item -Path $OutFileWin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Win\$Timestamp-Win.txt" + Remove-Item $OutFileWin + Start-Sleep -Seconds 5 + + #Get Powered On VM's + $vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "windows7Guest" ` + -or $_.GuestID -eq "windows7_64Guest" ` + -or $_.GuestID -eq "windows7Server64Guest" ` + -or $_.GuestID -eq "windows8_64Guest" ` + -or $_.GuestID -eq "windows8Server64Guest" ` + -or $_.GuestID -eq "windows9Server64Guest" ` + -or $_.GuestID -eq "winLonghorn64Guest" ` + -or $_.GuestID -eq "winLonghornGuest" ` + -or $_.GuestID -eq "winNetStandardGuest" ` + -or $_.GuestID -eq "winNetEnterpriseGuest" ` + -or $_.GuestID -eq "windows9_64Guest" ` + -or $_.GuestID -eq "windows2019srv_64Guest" ` + -or $_.GuestID -eq "windows2019srvNext_64Guest" ` + -or $_.GuestID -eq "windows2022srvNext_64Guest" + ) } + $vmviewwin = $vmwin | Get-View + + $Outputwin = "" + + #Loop through VM's, NIC's, and IP addresses. + Foreach ($v in $vmviewwin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputWin += $IP + "`n" + } + } + } + } + + #If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline} + If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline } + + + + ##Linux + + #Output File + $OutFileLin = "c:\inetpub\wwwroot\Lin.txt" + $Date = Get-Date -UFormat "%Y%m%d%H%M%S" + Get-Item -Path $OutFileLin | Copy-Item -Destination "F:\GetVMwareVMGuestIPsForPA\Backup\Lin\$Timestamp-Lin.txt" + Remove-Item $OutFileLin + Start-Sleep -Seconds 5 + + #Get Powered On VM's + $vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "centos6_64Guest" ` + -or $_.GuestID -eq "centos64Guest" ` + -or $_.GuestID -eq "centos7_64Guest" ` + -or $_.GuestID -eq "oracleLinux64Guest" ` + -or $_.GuestID -eq "oracleLinux7_64Guest" ` + -or $_.GuestID -eq "other26xLinux64Guest" ` + -or $_.GuestID -eq "rhel4Guest" ` + -or $_.GuestID -eq "rhel5Guest" ` + -or $_.GuestID -eq "rhel5_64Guest" ` + -or $_.GuestID -eq "rhel6Guest" ` + -or $_.GuestID -eq "rhel6_64Guest" ` + -or $_.GuestID -eq "rhel7_64Guest" ` + -or $_.GuestID -eq "rhel8_64Guest" ` + -or $_.GuestID -eq "rhel9_64Guest" ` + -or $_.GuestID -eq "sles11_64Guest" ` + -or $_.GuestID -eq "sles12_64Guest" ` + -or $_.GuestID -eq "ubuntu64Guest") } + $vmviewlin = $vmLin | Get-View + + $OutputLin = "" + + #Loop through VM's, NIC's, and IP addresses. + Foreach ($v in $vmviewlin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputLin += $IP + "`n" + } + } + } + } + + #If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline} + If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline } + + Disconnect-Viserver -Server itdvmvc1.nd.gov,itdvmvc2.nd.gov -Confirm:$false + Stop-Transcript \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPs.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPs.ps1 new file mode 100644 index 0000000..d53ce5e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPs.ps1 @@ -0,0 +1,116 @@ +<# Scheduled Task metadata +General + Get IPs for PA + run as ndgov\!itdvcenterppa + run whether user is logged on or not + Triggers + Daily, 11am + Daily, 11pm +Actions + C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1" +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + + +Start-Transcript C:\ITDSCRIPT\Logs\GetIPs.txt -Append +#Add-PSSnapin VMware.VimAutomation.Core +Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false + +#Connect +Connect-VIServer itdvmvc1.nd.gov, itdvmvc2.nd.gov + + +##Windows + + +#Output File +$OutFileWin = "c:\inetpub\wwwroot\Win.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileWin | Copy-Item -Destination "D:\Backup\Win\$Date-Win.txt" +Remove-Item $OutFileWin +Start-Sleep -Seconds 5 + + +#Get Powered On VM's +$vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "windows7Guest" ` + -or $_.GuestID -eq "windows7_64Guest" ` + -or $_.GuestID -eq "windows7Server64Guest" ` + -or $_.GuestID -eq "windows8_64Guest" ` + -or $_.GuestID -eq "windows8Server64Guest" ` + -or $_.GuestID -eq "windows9Server64Guest" ` + -or $_.GuestID -eq "winLonghorn64Guest" ` + -or $_.GuestID -eq "winLonghornGuest" ` + -or $_.GuestID -eq "winNetStandardGuest" ` + -or $_.GuestID -eq "winNetEnterpriseGuest" ` + -or $_.GuestID -eq "windows9_64Guest" ` + -or $_.GuestID -eq "windows2019srv_64Guest" ` + -or $_.GuestID -eq "windows2019srvNext_64Guest") } +$vmviewwin = $vmwin | Get-View + +$Outputwin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewwin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputWin += $IP + "`n" + } + } + } +} + +#If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline} +If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline } + + + +##Linux + +#Output File +$OutFileLin = "c:\inetpub\wwwroot\Lin.txt" +$Date = Get-Date -UFormat "%Y%m%d%H%M%S" +Get-Item -Path $OutFileLin | Copy-Item -Destination "D:\Backup\Lin\$Date-Lin.txt" +Remove-Item $OutFileLin +Start-Sleep -Seconds 5 + +#Get Powered On VM's +$vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" ` + -and ($_.GuestID -eq "centos6_64Guest" ` + -or $_.GuestID -eq "centos64Guest" ` + -or $_.GuestID -eq "centos7_64Guest" ` + -or $_.GuestID -eq "oracleLinux64Guest" ` + -or $_.GuestID -eq "oracleLinux7_64Guest" ` + -or $_.GuestID -eq "rhel4Guest" ` + -or $_.GuestID -eq "rhel5Guest" ` + -or $_.GuestID -eq "rhel5_64Guest" ` + -or $_.GuestID -eq "rhel6Guest" ` + -or $_.GuestID -eq "rhel6_64Guest" ` + -or $_.GuestID -eq "rhel7_64Guest" ` + -or $_.GuestID -eq "sles11_64Guest" ` + -or $_.GuestID -eq "sles12_64Guest" ` + -or $_.GuestID -eq "ubuntu64Guest") } +$vmviewlin = $vmLin | Get-View + +$OutputLin = "" + +#Loop through VM's, NIC's, and IP addresses. +Foreach ($v in $vmviewlin) { + Foreach ($nic in $v.Guest.Net) { + Foreach ($IP in $nic.IPAddress) { + If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") { + $OutputLin += $IP + "`n" + } + } + } +} + +#If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline} +If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline } + + +Stop-Transcript \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzure.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzure.ps1 new file mode 100644 index 0000000..c841686 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzure.ps1 @@ -0,0 +1,149 @@ +<# Scheduled Task metadata +General + Get IPs for PA - Azure + run as ndgov\svcitdazurescript + run whether user is logged on or not + Triggers + Daily, 2pm - repeat every 1 hour indefinitely +Actions + C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsAzure.ps1" +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + + +Start-Transcript C:\itdscript\Logs\GetIPsAzureB.txt -Append +$VerbosePerfrence = "Continue" + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$OutputPath = "C:\inetpub\wwwroot" + +$WindowsIPs = "" +$LinuxIPs = "" +$OutFileWin = $OutputPath + "\AzureWin.txt" +$OutFileLin = $OutputPath + "\AzureLin.txt" +Remove-Item $OutFileWin +Remove-Item $OutFileLin + + +$username="svcitdazurescript@nd.gov" +$usernameg="svcitdazurescript@ndstate.onmicrosoft.com" +#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat +$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString +$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString +$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password +$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg + +Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud -Verbose + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} + +Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) +{ + Set-AzureRMContext -SubscriptionObject $subscription + $WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"} + $LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $WindowsVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $WindowsIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $WindowsIPs += $privateip.privateIPAddress + "`n" + } + } + } + + foreach($vm in $LinuxVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $LinuxIPs += $private.privateIPAddress + "`n" + } + } + elseif($privateip.privateIPAddress -ne $null) + { + $LinuxIps += $privateip.privateIPAddress + "`n" + } + } + } +} + +If ($WindowsIPs -ne "" -and $WindowsIPs.Length -gt 150) {$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force} +If ($LinuxIPs -ne ""-and $LinuxIPs.Length -gt 150) {$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzureBackup.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzureBackup.ps1 new file mode 100644 index 0000000..51734ff --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsAzureBackup.ps1 @@ -0,0 +1,104 @@ +<# Scheduled Task metadata +General + Get IPs for PA - Azure Backup + run as ndgov\svcitdazurescript + run whether user is logged on or not + Triggers + Daily, 4:12pm - repeat every 1 hour indefinitely +Actions + C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsAzureBackup.ps1" +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + +start-transcript D:\zm.log -force +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$OutputPath = "C:\inetpub\wwwroot" +$OutputBackupPath = "C:\inetpub\wwwroot\AzureBak\" +$CurrentDateTime = Get-Date -UFormat "%Y%m%d%H%M%S" + + +$BackupIPs = "" +$OutFileBak = $OutputPath + "\AzureBak.txt" +$OutFileBakBackup = $OutputBackupPath + "\AzureBak-$CurrentDateTime.txt" + +Remove-Item $OutFileBak + + +$username="svcitdazurescript@nd.gov" +$usernameg="svcitdazurescript@ndstate.onmicrosoft.com" +#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat +$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString +$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString +$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password +$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg + +Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) + { + Set-AzureRMContext -SubscriptionObject $subscription + $BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $BackupVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $BackupIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $BackupIPs += $privateip.privateIPAddress + "`n" + } + } + } + } + +Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg + +$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"} +foreach($subscription in $subscriptions) +{ + Set-AzureRMContext -SubscriptionObject $subscription + $BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"} + $nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null} + + foreach($vm in $BackupVMs) + { + $vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id + foreach($vmnicinterface in $vmnicinterfaces) + { + $nic = $nics | Where-Object {$_.Id -eq $vmnicinterface} + $privateip = $nic.IpConfigurations | Select PrivateIPAddress + If($privateip.count -gt 1) + { + foreach($private in $privateip) + { + $BackupIPs += $private.privateIPAddress + "`n" + } + } + elseIf($privateip.privateIPAddress -ne $null) + { + $BackupIPs += $privateip.privateIPAddress + "`n" + } + } + } +} + +If ($BackupIPs -ne "") { + $BackupIPs | Out-File $OutFileBak -Encoding ASCII -NoNewline -Force + $BackupUPs | Out-File $OutFileBakBackup -Encoding ascii -NoNewline -Force + } diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsMonitor.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsMonitor.ps1 new file mode 100644 index 0000000..ddfbe97 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/GetIPsMonitor.ps1 @@ -0,0 +1,134 @@ +<# Scheduled Task metadata +General + Get IPs for PA - Azure Backup + run as ndgov\!itdvcenterscript + run whether user is logged on or not + Triggers + Daily, 11:30am - repeat every 1 hour indefinitely +Actions + C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsMonitor.ps1" +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + + +#cdfelchle 7/12/16 + +#Files to Monitor +$FileCheckWin = "c:\inetpub\wwwroot\win.txt" +$FileCheckLin = "c:\inetpub\wwwroot\lin.txt" +$FileCheckBak = "c:\inetpub\wwwroot\AzureBak.txt" +$FileCheckWinAz = "c:\inetpub\wwwroot\Azurewin.txt" +$FileCheckLinAz = "c:\inetpub\wwwroot\Azurelin.txt" + +#E-mail Initialization and Construction +$emailSubject = "VMware-PA Integration Failure" +$emailRelay = "apprelay2.nd.gov" +$emailBody = +"Scripting Server Error Report (ITDVMVCP1SCRIPT) +------------------------------------------ +" +$emailRecipients = "itdvctremailalerts@nd.gov" +$emailSender = "itdvmvcp1script@nd.gov" + +#File Presence Check +$WindowsPresent = Test-Path $FileCheckWin +$LinuxPresent = Test-Path $FileCheckLin +$AzureWindowsPresent = Test-Path $FileCheckWinAz +$AzureLinuxPresent = Test-Path $FileCheckLinAz +$AzureBakPresent = Test-Path $FileCheckBak + + +#Flag to send e-mail +$SendEmail = $False + + +#File Presence Check +If ($WindowsPresent -eq $False){ + $SendEmail = $True + $emailBody += $FileCheckWin + " --- Missing File`n" + } + +If ($LinuxPresent -eq $False){ + $SendEmail = $True + $emailBody += $FileCheckLin + " --- Missing File`n" + } + +If ($AzureWindowsPresent -eq $False){ + $SendEmail = $True + $emailBody += $FileCheckWinAz + " --- Missing File`n" + } + +If ($AzureLinuxPresent -eq $False){ + $SendEmail = $True + $emailBody += $FileCheckLinAz + " --- Missing File`n" + } + +If ($AzureBakPresent -eq $False){ + $SendEmail = $True + $emailBody += $FileCheckBak + " --- Missing File`n" + } + + +#File Size Check +If ($WindowsPresent -eq $True -and (Get-Item $FileCheckWin).length -lt 1000){ + $SendEmail = $True + $emailBody += "$FileCheckWin --- File size is less than 1kb`n" + } + +If ($LinuxPresent -eq $True -and (Get-Item $FileCheckLin).length -lt 1000){ + $SendEmail = $True + $emailBody += "$FileCheckLin --- File size is less than 1kb`n" + } + +If ($AzureWindowsPresent -eq $True -and (Get-Item $FileCheckWinAz).length -lt 100){ + $SendEmail = $True + $emailBody += "$FileCheckWinAz --- File size is less than 1kb`n" + } + +If ($AzureLinuxPresent -eq $True -and (Get-Item $FileCheckLinAz).length -lt 100){ + $SendEmail = $True + $emailBody += "$FileCheckLinAz --- File size is less than 1kb`n" + } + +If ($AzureBakPresent -eq $True -and (Get-Item $FileCheckBak).length -lt 10){ + $SendEmail = $True + $emailBody += "$FileCheckBak --- File size is less than 10 bytes`n" + } + + + +#File Age Check +$CurrentTime = Get-Date + +If ($WindowsPresent -eq $True -and (Get-Item $FileCheckWin).LastWriteTime -lt $CurrentTime.AddHours(-13)){ + $SendEmail = $True + $emailBody += "$FileCheckWin --- File is older than 12 hours`n" + } + +If ($LinuxPresent -eq $True -and (Get-Item $FileCheckLin).LastWriteTime -lt $CurrentTime.AddHours(-13)){ + $SendEmail = $True + $emailBody += "$FileCheckLin --- File is older than 12 hours`n" + } + +If ($AzureWindowsPresent -eq $True -and (Get-Item $FileCheckWinAz).LastWriteTime -lt $CurrentTime.AddHours(-13)){ + $SendEmail = $True + $emailBody += "$FileCheckWinAz --- File is older than 12 hours`n" + } + +If ($AzureLinuxPresent -eq $True -and (Get-Item $FileCheckLinAz).LastWriteTime -lt $CurrentTime.AddHours(-13)){ + $SendEmail = $True + $emailBody += "$FileCheckLinAz --- File is older than 12 hours`n" + } + +If ($AzureBakPresent -eq $True -and (Get-Item $FileCheckBak).LastWriteTime -lt $CurrentTime.AddHours(-13)){ + $SendEmail = $True + $emailBody += "$FileCheckBak --- File is older than 12 hours`n" + } + + +If ($SendEmail -eq $True){ + Send-MailMessage -To $emailRecipients -From $emailSender -Subject $emailSubject -Body $emailBody -SmtpServer $emailRelay + } \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/vmconfig.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/vmconfig.ps1 new file mode 100644 index 0000000..4925d58 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/Legacy/vmconfig.ps1 @@ -0,0 +1,87 @@ +<# Scheduled Task metadata +General + Old-VMware Billing + run as ndgov\!itdvcenterscript (required for SQL Database access) + run whether user is logged on or not + Triggers + Daily, 5am +Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\vmconfig.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop +#> + + +Start-Transcript C:\ITDSCRIPT\Logs\VMConfig.txt +Add-PSSnapin VMware.VimAutomation.Core +Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false +Connect-VIServer -Server itdvmvcp1.nd.gov,itdvmvcp2.nd.gov,itdvmvc1.nd.gov,itdvmvc2.nd.gov +#Connect-VIServer -Server itdvmvcp2.nd.gov + + +########################### +## Functions # +########################### + +### +### Override Invoke-SQLCmd cmdlet in order to display proper error Handling. +### +function Invoke-SQLCmd ([string] $ServerInstance, [string] $Database, [String] $Query) +{ + Try + { + $conn = new-object system.data.SqlClient.SqlConnection("Data Source=$ServerInstance;Integrated Security=TRUE;Initial Catalog=$Database"); + $ds = new-object "System.Data.DataSet" "dsChildSites" + + $da = new-object "System.Data.SqlClient.SqlDataAdapter" ($Query, $conn) + $fillcnt = $da.Fill($ds) + $conn.Close() + + $dtChild = new-object "System.Data.DataTable" "dsChildSites" + $dtChild = $ds.Tables[0] + $dtChild | FOREACH-OBJECT -process { + $_ + } + } + Catch + { + write-output $Query + Throw $_ + } +} + +#$Servers = Get-VM | Where-Object {$_.PowerState -like 'PoweredOn'} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name +$Servers = Get-VM | Where-Object {($_ | Get-Harddisk).count -ne 0} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name + + +$SQLServer = "ITDSQL16P1\SQL16P1" +$DB = "ITD-SRS-Billing" + +$Connection = New-Object System.Data.SQLClient.SQLConnection +$Connection.ConnectionString = "server='$SQLServer';database='$DB';Integrated Security=TRUE;" +$Connection.Open() +$Command = New-Object System.Data.SQLClient.SQLCommand +$Command.Connection = $Connection + +$Date = "'" + (Get-Date).ToString('yyyy/MM/dd') + "'" + +$sql = "delete from [VMware_VCenter_VMs] where snapshotdate = $Date;" +Invoke-SQLCmd -ServerInstance $SQLServer -Database $DB -Query $sql + +foreach($Server in $Servers) { + $ServerName = "'" + $Server.Name + "'" + $ServerMemoryMB = $Server.MemoryMB + $ServerNumCPU = $Server.NumCPU + $ServerHardDiskSizeGB = $Server.HardDiskSizeGB + $ServerHost = "'" + $Server.VMHost + "'" + $sql ="INSERT INTO [VMware_VCenter_VMs] (ServerName, SnapshotDate, VMName, Memory_MB, Num_VCPU, Disk_MB, ESXHostName) Values ('None', $Date, $ServerName, $ServerMemoryMB, $ServerNumCPU, $ServerHardDiskSizeGB, $ServerHost);" + Invoke-SQLCmd -ServerInstance $SQLServer -Database $DB -Query $sql + +} + +$Connection.Close() +Stop-Transcript + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SetVMTagAndMoveToAppNameFolderTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SetVMTagAndMoveToAppNameFolderTask.ps1 new file mode 100644 index 0000000..a513325 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SetVMTagAndMoveToAppNameFolderTask.ps1 @@ -0,0 +1,30 @@ +<# Scheduled Task metadata +General + SetVMTagAndMoveToAppNameFolder + run as ndgov\svcitdiaassched + run whether user is logged on or not + run with highest privileges + Triggers + Daily, 1pm +Actions + old powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SetVMTagAndMoveToAppNameFolderTask.ps1" + new "C:\Program Files\PowerShell\7\pwsh.exe" -file "F:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SetVMTagAndMoveToAppNameFolderTask.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 3 days + if the running task does not end when requested, force it to stop +#> + + +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "F:\SetVMTagAndMoveToAppNameFolder\Logs\SetVMTagAndMoveToAppNameFolderTask-$Timestamp.log" +Start-Transcript $TranscriptPath + +Connect-ITDvCenter -Credential $svcitdvmvcauto + +Set-ITDVMwareVMTagFromSharePoint -SharePointCredential $svcitdiaassprw -Verbose + +Move-ITDVMwareVMToAppNameFolder -Credential $svcitdvmvcauto -Verbose + +Disconnect-VIServer -Server * -Force -Confirm:$false \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/StartDatastoreUnmap.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/StartDatastoreUnmap.ps1 new file mode 100644 index 0000000..6c9004d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/StartDatastoreUnmap.ps1 @@ -0,0 +1,12 @@ +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "D:\PowerShellTasks\StartDatastoreUnmap\Logs\StartDatastoreUnmapTask-$Timestamp.log" +Start-Transcript $TranscriptPath + +try +{ + Start-ITDVMwareDatastoreUnmap -Credential $svcitdvmvcauto -Verbose +} +catch +{ + Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task StartITDVMwareDatastoreUnmap errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareAppNameTagsFromSharePointTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareAppNameTagsFromSharePointTask.ps1 new file mode 100644 index 0000000..b8e773e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareAppNameTagsFromSharePointTask.ps1 @@ -0,0 +1,28 @@ +<# Scheduled Task metadata +General + SetVMTagNadMovToAppNameFolder + run as ndgov\svcitdiaassched + run whether user is logged on or not + run with highest privileges + Triggers + Daily, 8am + Disabled +Actions + powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SyncVMwareAppNameTagsFromSharePoint.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 3 days + if the running task does not end when requested, force it to stop +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "D:\PowerShellTasks\SyncVMwareAppNameTagsFromSharePoint\Logs\SyncVMwareAppNameTagsFromSharePointTask-$Timestamp.log" +Start-Transcript $TranscriptPath + +try { + Sync-ITDVMwareSharePointAppNameTags -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose +} +catch { + Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task SyncVMwareAppNameTagsFromSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareDatastoresToSharePointTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareDatastoresToSharePointTask.ps1 new file mode 100644 index 0000000..4c20971 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareDatastoresToSharePointTask.ps1 @@ -0,0 +1,34 @@ +<# Scheduled Task metadata +General + SetVMTagNadMovToAppNameFolder + run as ndgov\svcitdiaassched + run whether user is logged on or not + run with highest privileges + Triggers + Daily, 10:15am, repeat every 8 hours +Actions + "C:\Program Files\PowerShell\7\pwsh.exe" -file "D:\PowerShellTasks\SyncVMwareDatastoresToSharePoint\SyncVMwareDatastoresToSharePoint.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 3 days + if the running task does not end when requested, force it to stop +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "F:\SyncVMwareDatastoresToSharePoint\Logs\SyncVMwareDatastoresToSharePoint-$Timestamp.log" +Start-Transcript $TranscriptPath + +try +{ + Connect-ITDvCenter -Credential $svcitdvmvcauto + Sync-ITDVMwareSharePointDatastoreRecord -SharePointCredential $svcitdiaassprw -verbose + Disconnect-VIServer -Server * -Confirm:$flse +} +catch +{ + Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task SyncVMwareDatastoresToSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov +} + + +Stop-Transcript \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareHostTags.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareHostTags.ps1 new file mode 100644 index 0000000..df15ae6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareHostTags.ps1 @@ -0,0 +1,10 @@ +Connect-HPOVMgmt -Hostname itdoneviewp1.nd.gov -Credential $AdminCred -LoginAcknowledge + +$VMwareHosts = Get-VMHost +$HPOVServers = Get-HPOVServer | Select-Object *,@{n='Enclosure';e={$_.Name.split(',')[0]}} + +ForEach($VMwareHost in $VMwareHosts) +{ + $HPOVServer = $HPOVServers | where-object ServerName -eq $VMwareHost.Name + $VMwareHost | New-TagAssignment -Tag $HPOVServer.Enclosure -Server $VMwareHost.Uid.split('@')[1].split(':')[0] +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareTagsFromSharePointTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareTagsFromSharePointTask.ps1 new file mode 100644 index 0000000..8e60f95 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareTagsFromSharePointTask.ps1 @@ -0,0 +1,34 @@ +<# Scheduled Task metadata +General + SyncVMwareSharePointTags + run as ndgov\svcitdiaassched + run whether user is logged on or not + run with highest privileges + Triggers + Daily, 10:15am, repeat every 8 hours +Actions + powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SyncVMwareTagsFromSharePoint.ps1" + "C:\Program Files\PowerShell\7\pwsh.exe" -file "F:\SyncVMwareTagsFromSharePoint\SyncVMwareTagsFromSharePointTask.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 3 days + if the running task does not end when requested, force it to stop +#> + +$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S" +$TranscriptPath = "F:\SyncVMwareTagsFromSharePoint\Logs\SyncVMwareTagsFromSharePointTask-$Timestamp.log" +Start-Transcript $TranscriptPath + + + +try { + #Sync-ITDVMwareSharePointTags -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose + + Connect-ITDvCenter -Credential $svcitdvmvcauto + Sync-ITDVMwareSharePointTags -SharePointCredential $svcitdiaassprw -Verbose + Disconnect-VIServer -Server * -Confirm:$false +} +catch { + Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvc1script@nd.gov -Subject "Task SyncVMwareTagsFromSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareVMsToSql.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareVMsToSql.ps1 new file mode 100644 index 0000000..3db0fac --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Administration/Tasks/SyncVMwareVMsToSql.ps1 @@ -0,0 +1,62 @@ +<# Scheduled Task metadata +General + Old-VMware Billing + run as ndgov\!itdvcenterscript (required for SQL Database access) + run whether user is logged on or not + Triggers + Daily, 5am +Actions + old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\vmconfig.ps1" + new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1" + "C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1" + +Settings + allow task to be run on demand + stop the task if it runs longer than 1 hour -eq $true + if the running task does not end when requested, force it to stop + +SQL Query to check for most recent 2500 records +SELECT TOP (2500) [ServerName] + ,[SnapshotDate] + ,[VMName] + ,[Memory_MB] + ,[Num_VCPU] + ,[Disk_MB] + ,[ESXHostName] + FROM [ITD-SRS-Billing].[dbo].[VMWare_VCenter_VMs] + ORDER BY SnapshotDate DESC, VMName ASC + +#> +$Secret:!itdvcenterscript +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" +Start-Transcript F:\SyncVMwareVMsToSql\Logs\SyncVMwareVMsToSql-$Timestamp.log + +Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false +Connect-ITDvCenter + +$Datacenters = Get-Datacenter | Where-Object {$_.Name -notlike "*Normandy*" -and $_.Name -notlike "*Vantis*"} +$VMs = $Datacenters | Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "itdzmtest*"} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name + + +$SqlServer = "itdsql22p1.nd.gov\SQL22P1" +$Database = "ITD-SRS-Billing" +$Date = "'" + (Get-Date).ToString('yyyy/MM/dd') + "'" + +# remove today's entries if already there +Write-Verbose -Message "remove today's entries if already there" +$SqlQuery = "delete from [VMware_VCenter_VMs] where snapshotdate = $Date;" +Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery + +foreach($VM in $VMs) { + Write-Verbose -Message ("Begin " + $VM.Name) + $VMName = "'" + $VM.Name + "'" + $VMMemoryMB = $VM.MemoryMB + $VMNumCPU = $VM.NumCPU + $VMHardDiskSizeGB = $VM.HardDiskSizeGB + $VMHost = "'" + $VM.VMHost + "'" + $SqlQuery ="INSERT INTO [VMware_VCenter_VMs] (ServerName, SnapshotDate, VMName, Memory_MB, Num_VCPU, Disk_MB, ESXHostName) Values ('None', $Date, $VMName, $VMMemoryMB, $VMNumCPU, $VMHardDiskSizeGB, $VMHost);" + Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery + +} + +Stop-Transcript \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/azure-pipelines.yml new file mode 100644 index 0000000..06385a4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-VMware.Snapshot' + +variables: + major: 0 + minor: 1 + 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.Infra-VMware.Snapshot.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.Infra-VMware.Snapshot.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/build.ps1 new file mode 100644 index 0000000..ec72b63 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-VMware.Snapshot' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-VMware.Snapshot).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.nuspec new file mode 100644 index 0000000..cc0e8e4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-VMware.Snapshot + $VERSIONHERE$ + Zack Meier + Functions for VMware Snapshot tasks + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psd1 new file mode 100644 index 0000000..05380a6 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psd1 @@ -0,0 +1,133 @@ +# +# Module manifest for module 'ITD.Infra-VMware.Snapshot' +# +# Generated by: zmeier +# +# Generated on: 5/19/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.Infra-VMware.Snapshot.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + + # ID used to uniquely identify this module + GUID = 'b45cb1f1-f08c-4873-948b-232e3ce26418' + + # Author of this module + Author = 'zmeier' + + # Company or vendor of this module + CompanyName = 'Unknown' + + # Copyright statement for this module + Copyright = '(c) zmeier. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'Functions for VMware Virtual Machine tasks' + + # 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 = @() + + # 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 = @("ITD.Infra-Passwordstate","ITD.Infra-Networking-Infoblox","ITD.Shared-ServiceNow","ITD.Infra-VMware.VirtualMachine","ITD.Infra-VMware.Administration") + + } # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/ITD.Infra-VMware.Snapshot.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotTaskV3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotTaskV3.ps1 new file mode 100644 index 0000000..4629d67 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotTaskV3.ps1 @@ -0,0 +1,143 @@ +<# +.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-ITDVMwareVMSnapshotTaskV3 { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string[]] + $VMName, + + [Parameter(Mandatory = $true)] + [string] + $Name, + + [string] + $Description, + + [datetime] + $DateTime, + + [string[]] + $Email + ) + + begin { + + } + + process { + Write-Verbose -Message "Start Loop" + ForEach ($VName in $VMName) { + Write-Verbose -Message "Start $VMName" + $VM = $null + + + $VM = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } -ErrorAction SilentlyContinue + If ($VM) { + $ViServer = $VM.Uid.split('@')[1].split(':')[0] + + $NewSnapshotParams = @{ + Name = $Name; + RunAsync = $true; + } + switch ($PSBoundParameters.Keys) { + Description { + $NewSnapshotParams.Description = $Description + } + Memory { + $NewSnapshotParams.Memory = $Memory; + $NewSnapshotParams.RunAsync = $false; + } + } + + Write-Verbose -Message ("Validate DateTime is in the future") + + If ($DateTime -lt (Get-Date)) { + Write-Warning -Message "DateTime is in the past, recursively running the function again, adjusting start time to 60 seconds from now." + $NewITDVMwareVMSnapshotTaskParams = @{ + VMName = $VMName; + Name = $Name; + Description = $Description; + DateTime = (Get-Date).AddSeconds(60); + Email = ($Email -join ','); + } + New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams + } + else { + Write-Verbose -Message ("Attempt sched task creation") + try { + $si = Get-View ServiceInstance -Server $VIServer + $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer + + $spec = New-Object VMware.Vim.ScheduledTaskSpec + $spec.Name = $Name, $VName -join '_' + $spec.Description = "$Description" + $spec.Enabled = $true + switch ($PSBoundParameters.Keys) { + Email { + $spec.Notification = $Email + } + } + + $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler + $spec.Scheduler.runat = $DateTime + + $spec.Action = New-Object VMware.Vim.MethodAction + $spec.Action.Name = "CreateSnapshot_Task" + + $Memory = $false + $Quiesce = $false + + @($Name, $Description, $Memory, $Quiesce) | ForEach-Object { + $arg = New-Object VMware.Vim.MethodActionArgument + $arg.Value = $_ + $spec.Action.Argument += $arg + } + Start-Sleep -Seconds 20 + + try { + $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec) + } + catch [System.Management.Automation.MethodInvocationException] { + Write-Warning -Message "System.Management.Automation.MethodInvocationException" + If ($error[0].Exception.Message -like "*You have attempted to schedule the scheduler at a time value*" -and $error[0].Exception.Message -Like "* in the past,*") { + Write-Warning -Message "DateTime is in the past, recursively running the function again, adjusting start time to 60 seconds in the future from now." + $NewITDVMwareVMSnapshotTaskParams = @{ + VMName = $VMName; + Name = $Name; + Description = $Description; + DateTime = (Get-Date).AddSeconds(60); + Email = $Email; + } + New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams + } + } + catch { + Write-Warning -Message "Default" + } + + } + catch { + Write-Error $error[0] + } + } + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotV3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotV3.ps1 new file mode 100644 index 0000000..df91678 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/New-ITDVMwareVMSnapshotV3.ps1 @@ -0,0 +1,61 @@ +<# +.SYNOPSIS + A short one-line action-based description, e.g. 'Tests if a function is valid' +.DESCRIPTION + Create a new snapshot of a VMware Virtual Machine +.NOTES + Create a new snapshot of a VMware Virtual Machine +.LINK + Specify a URI to a help page, this will show when Get-Help -Online is used. +.EXAMPLE + New-ITDVMwareVMSnapshot -VMName itdwinautot1.nd.gov -Name "Before Upgrade to 7.0U3k" -Description "Before Upgrade, delete after 3/3/2023" +#> + +function New-ITDVMwareVMSnapshotV3 { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string[]] + $VMName, + + [Parameter(Mandatory = $true)] + [string] + $Name, + + [string] + $Description, + + [switch] + $Memory + ) + + begin { + } + + process { + ForEach ($VName in $VMName) { + $VM = Get-VM -Name $VName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + + $NewSnapshotParams = @{ + Name = $Name; + RunAsync = $true; + } + switch ($PSBoundParameters.Keys) { + Description { + $NewSnapshotParams.Description = $Description + } + Memory { + $NewSnapshotParams.Memory = $Memory; + $NewSnapshotParams.RunAsync = $false; + } + } + + $NewSnapshotParams + $VM | New-Snapshot @NewSnapshotParams + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotTaskExpired.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotTaskExpired.ps1 new file mode 100644 index 0000000..bb9f3a0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotTaskExpired.ps1 @@ -0,0 +1,58 @@ +<# +.SYNOPSIS + This function for cleanup of AutoSnap* scheduled tasks that have completed their lifecycle. +.DESCRIPTION + This function for cleanup of vCenter scheduled tasks named AutoSnap*, all of which have completed their lifecycle. +.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 Remove-ITDVMwareVMSnapshotTaskExpired { + [CmdletBinding()] + param ( + [switch] + $WhatIf + ) + + begin { + + } + + process { + Write-Verbose -Message ("Gathering all scheduled tasks with AutoSnap in the task name, this will take some time") + $si = Get-View ServiceInstance + $scheduledTaskManager = Get-View $Si.Content.ScheduledTaskManager + $AllScheduledTasks = Get-View -Id $scheduledTaskManager.ScheduledTask | Where-Object { $_.Info.Name -like "AutoSnap*" } | Select-Object -Unique + ForEach ($ScheduledTask in $AllScheduledTasks) { + Write-Verbose -Message ("Start " + $ScheduledTask.Info.Name) + If ($ScheduledTask.Info.Name -like "AutoSnap*") { + # Double check snapshot task + If ($ScheduledTask.Info.PrevRunTime -lt (Get-Date) -and $ScheduledTask.Info.NextRunTime -eq $null) { + # if run once and completed + + If ($WhatIf){ + Write-Host -Message ("What if: Performing the operation RemoveScheduledTask() on target " + $ScheduledTask.Info.Name) + } Else { + Write-Verbose -Message ("Removing scheduled task named " + $ScheduledTask.Info.Name) + $ScheduledTask.RemoveScheduledTask() + } + + + } + } + Else { + # do nothing + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotV3.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotV3.ps1 new file mode 100644 index 0000000..859c0e9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Public/Remove-ITDVMwareVMSnapshotV3.ps1 @@ -0,0 +1,42 @@ +<# +.SYNOPSIS + A short one-line action-based description, e.g. 'Tests if a function is valid' +.DESCRIPTION + Create a new snapshot of a VMware Virtual Machine +.NOTES + Create a new snapshot of a VMware Virtual Machine +.LINK + Specify a URI to a help page, this will show when Get-Help -Online is used. +.EXAMPLE + New-ITDVMwareVMSnapshot -ComputerName itdwinautot1.nd.gov -Name "Before Upgrade to 7.0U3k" -Description "Before Upgrade, delete after 3/3/2023" +#> + +function Remove-ITDVMwareVMSnapshotV3 { + [CmdletBinding()] + param ( + [string] + $ComputerName, + + [string] + $Name + ) + + begin { + + } + + process { + + $VM = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + + $GetSnapshotParams = @{ + Name = $Name + } + + $VM | Get-Snapshot @GetSnapshotParams | Remove-Snapshot -Confirm:$false + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/README.md b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/SQL/snapshottable.sql b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/SQL/snapshottable.sql new file mode 100644 index 0000000..a132410 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/SQL/snapshottable.sql @@ -0,0 +1,37 @@ +CREATE TABLE Infra_VMware_VirtualMachine_VMSnapshots_NPD ( + ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, + VMName varchar(255) NOT NULL, + DateTime DateTime NOT NULL, + RequestedBy varchar(255) NOT NULL, + DurationHours int NOT NULL, + Status varchar(255) NOT NULL, + NotifyEmail varchar(255), + TakenDateTime DateTime, + ExpireDateTime DateTime, + DeleteDateTime DateTime, + PSUJobIdRequest int, + PSUJobIdSchedule int, + PSUJobIdDelete int +) + +CREATE TABLE Infra_VMware_VirtualMachine_VMSnapshots_PRD ( + ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, + VMName varchar(255) NOT NULL, + DateTime DateTime NOT NULL, + RequestedBy varchar(255) NOT NULL, + DurationHours int NOT NULL, + Status varchar(255) NOT NULL, + NotifyEmail varchar(255), + TakenDateTime DateTime, + ExpireDateTime DateTime, + DeleteDateTime DateTime +) + +ALTER TABLE Infra_VMware_VirtualMachine_VMSnapshots_PRD +DROP COLUMN PSUJobId + +ALTER TABLE Infra_VMware_VirtualMachine_VMSnapshots_PRD +ADD PSUJobIdSchedulet int + +ALTER TABLE Infra_VMware_VirtualMachine_VMSnapshots_PRD +ADD PSUJobIdDelete int \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Scripts_PSUDashboard/NewITDVMwareVMSnapshotTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Scripts_PSUDashboard/NewITDVMwareVMSnapshotTask.ps1 new file mode 100644 index 0000000..1e3bcdb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.Snapshot/Scripts_PSUDashboard/NewITDVMwareVMSnapshotTask.ps1 @@ -0,0 +1,23 @@ +New-UDApp -Title 'NewITDVMwareVMSnapshotTask' -Pages @( + New-UDPage -Name "NewITDVMwareVMSnapshotTask" -Content { + New-UDForm -Content { + New-UDTextbox -Label 'VMName' -Id 'VMName' + New-UDTextbox -Label 'HoursToKeep' -Id 'HoursToKeep' + New-UDDatePicker -Label 'StartDate' -Id "StartDate" -Variant dialog + New-UDTimePicker -Label 'StartTime' -Id "StartTime" + + } -OnSubmit { + #Show-UDToast -Message $EventData.txtTextField + #Show-UDToast -Message $EventData.chkCheckbox + #Invoke-PSUScript -Script 'Test-FormSubmission.ps1' -VMName $EventData.VMName + #"Current User = $User, StartDate = " + $EventData.StartDate + " " + $EventData.StartTime + + + + $StartDateTime = $EventData.StartDate.Date + $StartDateTime = $StartDateTime.AddHours($EventData.StartTime.Hour) + $StartDateTime = $StartDateTime.AddMinutes($EventData.StartTime.Minute) + Show-UDToast -Message ("Start Date/Time is: " + $StartDateTime) -Duration 20000 + } + } +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/azure-pipelines.yml new file mode 100644 index 0000000..7680e2f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.Infra-VMware.VirtualMachine' + +variables: + major: 2 + minor: 0 + 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.Infra-VMware.VirtualMachine.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.Infra-VMware.VirtualMachine.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/build.ps1 new file mode 100644 index 0000000..c984d56 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.Infra-VMware.VirtualMachine' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.Infra-VMware.VirtualMachine).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_script.ps1 new file mode 100644 index 0000000..aa65f0b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_script.ps1 @@ -0,0 +1,85 @@ +Param( + [string] + $SCTaskNum +) + +New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred +Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + +$Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-like', 'Windows Guest OS complete. Hardware team review.'), '-and', @('state', '-eq', '2') # 2 = 'work in progress' +$OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object Number -EQ $SCTaskNum +} + +Write-Verbose -Message ("OpenTasks found: " + $OpenTasks.count) -Verbose +ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message $OpenTasks.Number -Verbose +} + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + Write-Verbose -Message "Start $SCTasknum" -Verbose + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $shortdescription = $SCTask.short_description + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable -WarningAction SilentlyContinue + + switch (($Ritm.CustomVariable | Where-Object Name -EQ target_platform).Value) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + $FormFQDN = ($RITM.CustomVariable | Where-Object Name -EQ "host_name").value + $FormHostName = $FormFQDN.split('.')[0] + + $Ci = Get-ServiceNowRecord -Table cmdb_ci -Filter @('name', '-eq', $FormHostName) + + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + switch ($target_platform) { + { $_ -like "*VMware*" } { + Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + Write-Verbose -Message ("$FormFQDN is a VMware VM. Determine if SRM was requested.") -Verbose + $hardware_platform = "VMware"; + $hardware_type = 'Virtual Machine' + + If ( ($Ritm.CustomVariable | Where-Object Name -EQ 'dr_protection').Value -eq 'No DR') { + Write-Verbose -Message ("$FormFQDN dr_protection equals 'No DR'") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum -CloseTask -Verbose + } + Else { + Write-Verbose -Message ("$FormFQDN dr_protection is requested") -Verbose + Write-Warning -Message ("SRM is requested, task will not auto close. -- ZM") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + Disconnect-ITDvCenter + } + { $_ -like "*Microsoft Virtual Machine*" } { + Write-Verbose -Message ("$FormFQDN is an Azure VM. DR is not an option, proceed.") -Verbose + $hardware_platform = "Azure"; + $hardware_type = 'Virtual Machine' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + #Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + { $_ -like "*HP*" } { + Write-Verbose -Message ("$FormFQDN is an HPE device.") -Verbose + $hardware_platform = 'HPE'; + $hardware_type = 'Physical' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + } + default { + $hardware_platform = 'Other' + Write-Warning -Message ("Ci found, but unavailable to determine hardware platform.") + } + } + +} + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_scriptV3_DONOTUSE.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_scriptV3_DONOTUSE.ps1 new file mode 100644 index 0000000..2dca795 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/Approve-ITDVMNewBuild_scriptV3_DONOTUSE.ps1 @@ -0,0 +1,89 @@ +Param( + [string] + $SCTaskNum +) + +New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred +Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + +$Filter = 'active=true^short_descriptionSTARTSWITHAutomated Server Build Task for Windows Machine' +$OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter | Sort-Object Number +If ($PSBoundParameters.ContainsKey("SCTaskNum")) { + Write-Verbose -Message "SCTaskNum parameter found, value is $SCTaskNum" + $OpenTasks = $OpenTasks | Where-Object Number -EQ $SCTaskNum +} + +Write-Verbose -Message ("OpenTasks found: " + $OpenTasks.count) -Verbose +ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message $OpenTasks.Number -Verbose +} + +ForEach ($OpenTask in $OpenTasks) { + $Ci = $null + $BuildComplete = $null + + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + Write-Verbose -Message "Start $SCTasknum" -Verbose + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $ShortDescription = $SCTask.short_description + #$RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet -WarningAction SilentlyContinue + + switch ( $Ritm.VariableSet.target_platform ) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + #$FormFQDN = ($RITM.CustomVariable | Where-Object Name -EQ "host_name").value + $FormFQDN = ($RITM.VariableSet.host_name) + $FormHostName = $FormFQDN.split('.')[0] + + #$Ci = Get-ServiceNowRecord -Table cmdb_ci -Filter @('name', '-eq', $FormHostName) + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $FormHostName) + + If ($Ci) { + Write-Verbose -Message ("Ci found, sys_id = " + $Ci.sys_id + ", name = " + $Ci.name + ", fqdn = " + $Ci.fqdn) -Verbose + } + Else { + switch ($target_platform) { + { $_ -like "*VMware*" } { + Connect-ITDvCenter -Credential $Secret:svcitdvmvcauto + Write-Verbose -Message ("$FormFQDN is a VMware VM. Determine if SRM was requested.") -Verbose + $hardware_platform = "VMware"; + $hardware_type = 'Virtual Machine' + + If ( ($Ritm.CustomVariable | Where-Object Name -EQ 'dr_protection').Value -eq 'No DR') { + Write-Verbose -Message ("$FormFQDN dr_protection equals 'No DR'") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum -CloseTask -Verbose + } + Else { + Write-Verbose -Message ("$FormFQDN dr_protection is requested") -Verbose + Write-Warning -Message ("SRM is requested, task will not auto close. -- ZM") -Verbose + Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + Disconnect-ITDvCenter + } + { $_ -like "*Microsoft Virtual Machine*" } { + Write-Verbose -Message ("$FormFQDN is an Azure VM. DR is not an option, proceed.") -Verbose + $hardware_platform = "Azure"; + $hardware_type = 'Virtual Machine' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + #Approve-ITDVMNewBuild -SCTaskNum $SCTaskNum + } + { $_ -like "*HP*" } { + Write-Verbose -Message ("$FormFQDN is an HPE device.") -Verbose + $hardware_platform = 'HPE'; + $hardware_type = 'Physical' + Write-Warning -Message ("Final close task is commented out until testing can occur. -- ZM") -Verbose + } + default { + $hardware_platform = 'Other' + Write-Warning -Message ("Ci found, but unavailable to determine hardware platform.") + } + } + } + +} + +Disconnect-ITDvCenter \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMWindowsSNow.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMWindowsSNow.ps1 new file mode 100644 index 0000000..022554f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMWindowsSNow.ps1 @@ -0,0 +1,4 @@ +# if a manually triggered build needs to occur, run this + +Update-Module ITD.Infra-VMware.VirtualMachine +New-ITDVMwareWindowsVM -ComputerName $FQDN -CPU $CPU -MemoryGB $MemoryGB -VlanId $VlanId -OS $OS -Environment $Environment -Datacenter $Datacenter -LicensingRestrictions $LicensingRestrictions \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMCsvFile.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMCsvFile.ps1 new file mode 100644 index 0000000..7dbc4aa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMCsvFile.ps1 @@ -0,0 +1,23 @@ +# send JSON payload to AA to create csv file that gets moved to itdwinautop1.nd.gov (and will be built) + +$RestMethodParams = @{ + Method = 'Post'; + Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d'; + Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV' }; + Body = [PSCustomObject]@{ + target_platform = "VMware" + target_hostname = 'itdk12cladgwp1.nd.gov'; + target_cpus = 4; + target_memory = 8; + target_osdisk = 80; + target_datadisk = 9; # this is now swap + target_subnet = '10.2.82.208/29'; + target_os = 'Windows Server 2022 Datacenter'; + target_environment = 'Production'; + target_vm_app_name = 'ITD-Edutech-ClassLink'; + target_datacenter = 'Bismarck'; + target_licensingrestrictions = 'No Licensing Restrictions'; + } | ConvertTo-Json; +} + +Invoke-RestMethod @RestMethodParams \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMFromCsv.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMFromCsv.ps1 new file mode 100644 index 0000000..b43e2d7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/New-ITDVMwareWindowsVMFromCsv.ps1 @@ -0,0 +1,77 @@ +# scheduled task that finds the oldest input file, reads it, and builds a VM with the parameters found + +$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S" +$TranscriptPath = "F:\AutoBuildLogs\$TimeStamp.log" +Start-Transcript $TranscriptPath + +$DriveLetter = 'F' +$CsvPath = ($DriveLetter + ":\AutoBuildInputFiles\") +$FailedPath = ($DriveLetter + ":\AutoBuildInputFiles\Failed") +$CompletedPath = ($DriveLetter + ":\AutoBuildInputFiles\Completed") + +$GetBuildFile = Get-ChildItem -Path $CsvPath -Filter *.csv | Sort-Object LastWriteTime | select -First 1 +Write-Warning -Message ("Found file " + $GetBuildFile.Name) + +If ($GetBuildFile) { + + $IaasAutoCred = Get-Secret -Name svcitdiaasauto + #$IaasAutoCred = $PrvCred + + Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore + + $InputParams = Import-Csv -Path $GetBuildFile.FullName + + $ComputerName = $InputParams.target_hostname.ToLower() + Send-MailMessage -From "itdwinauto@nd.gov" -To "vmware@nd.gov" -SmtpServer apprelay1.nd.gov -Body $InputParams -Subject ("AutoBuildFromFile-$ComputerName-" + $InputParams.target_platform) + + try { + switch ($InputParams.target_platform) { + 'azure' { + + } + 'vmware' { + Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred + + New-ITDVMwareWindowsVM -ComputerName $ComputerName ` + -CPU $InputParams.target_cpus ` + -MemoryGB $InputParams.target_memory ` + -DiskOS $InputParams.target_osdisk ` + -DiskSwap $InputParams.target_datadisk ` + -Subnet $InputParams.target_subnet ` + -OS $InputParams.target_os ` + -Environment $InputParams.target_environment ` + -Datacenter $InputParams.target_datacenter ` + -AppName $InputParams.target_vm_app_name ` + -LicensingRestrictions $InputParams.target_licensingrestrictions ` + -Credential $IaasAutoCred ` + -Verbose + + Move-Item -Path $GetBuildFile.FullName -Destination $CompletedPath + + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Provisioning'; + Units = 240; + Platform = 'PowerShell-VMware-VMWindows'; + } + + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) + + } + } + } + catch { + $error[0] + Write-Warning "Email vmware admins about failure" + $Body = $error[0] | Select-Object * + Send-MailMessage -From autobuild@nd.gov -To "vmware@nd.gov" -Subject "Failure-AutoBuildFromFile-$ComputerName" -SmtpServer apprelay.nd.gov -Body $Body + + Write-Warning "Error detected. Moving csv input file to folder Failed" + Move-Item -Path $GetBuildFile.FullName -Destination $FailedPath + } + Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue +} +Else { + Stop-Transcript + Get-Item -Path $TranscriptPath | Remove-Item +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/VMware-WindowsVMTools.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/VMware-WindowsVMTools.ps1 new file mode 100644 index 0000000..4d48b38 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/VMware-WindowsVMTools.ps1 @@ -0,0 +1,52 @@ +# enable upgrade at next reboot +$ToolsConfig = New-Object VMware.Vim.VirtualMachineConfigSpec +$ToolsConfig.tools = New-Object VMware.Vim.ToolsConfigInfo +$ToolsConfig.Tools.ToolsUpgradePolicy = 'upgradeAtPowerCycle' + +# single VM, enable +$vm = Get-VM -Name itdscmt1.nd.gov +($vm | Get-View).ReconfigVM($ToolsConfig) + +# get all WS +$AllVMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } +$AllVMsWindows = $AllVMs | Where-Object {$_.Guest.OSFullName -like "*Windows*"} + +$AllVMsDTAP = $AllVMsWindows | Get-TagAssignment -Category DTAP +$AllVMsTest = $AllVMsDTAP | Where-Object {$_.Tag.Name -eq 'Test'} +$AllVMsProd = $AllVMsDTAP | Where-Object {$_.Tag.Name -eq 'Production'} + +$AllVMsTest | Export-Csv "D:\OneDrive - State of North Dakota\AllTestVMs.csv" +$AllVMsProd | Export-Csv "D:\OneDrive - State of North Dakota\AllProdVMs.csv" + +ForEach($VM in $AllVMsTest){ + ($VM | Get-View).ReconfigVM($ToolsConfig) +} #### CHECK 2008 non-R2 x3 + +# get all Windows and ToolsVersion counts +$AllVMGuests = $AllVMs | Get-VMGuest +$AllVMGuests | select VMName, ToolsVersion + +# disable upgrade at next reboot +$ToolsConfig = New-Object VMware.Vim.VirtualMachineConfigSpec +$ToolsConfig.tools = New-Object VMware.Vim.ToolsConfigInfo +$ToolsConfig.Tools.ToolsUpgradePolicy = 'manual' + +$vm = Get-VM -Name itdscmt1.nd.gov +($vm | Get-View).ReconfigVM($ToolsConfig) + + +$AllVMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + + + +$AllVMs = Get-VM | Where-Object {$_.Name -like "*itd*" -and $_.Guest.OSFullName -notlike "*Windows*"} + + +# report +$AllVMsWindows | select Name,@{n='OS';e={$_.Guest.OSFullName}},@{n='ToolsVersion';e={($_ | Get-VMGuest).ToolsVersion}},@{n='ToolsPolicy';e={($_ | Get-View).config.tools.toolsupgradepolicy}} -ov ToolsReport | export-csv "D:\vmtools.csv" + +# set prod +ForEach($VM in $AllVMsWindows){ + Write-Warning -Message ($VM.Name) + ($VM | Get-View).ReconfigVM($ToolsConfig) +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/validate_newserver.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/validate_newserver.ps1 new file mode 100644 index 0000000..03f170d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Helpers/unused_to_review/validate_newserver.ps1 @@ -0,0 +1,45 @@ +$ComputerName = @" +itddmrdbmssqlu1.nd.gov +itddmrdbmssqld1.nd.gov +itddmrdbmsu1.nd.gov +itddmrdbmsd1.nd.gov +"@ + +$ComputerName = ConvertTo-Array -MultiLineString $ComputerName + +Invoke-Command -Credential $PrvCred -ComputerName $ComputerName -ScriptBlock { + Get-Process -Name ccmexec, cohesity*, nessus*, cortex*, vmware* +} | Sort-Object PSComputerName + +<# +# Add to Solarwinds +$Func = { + param($ComputerName) + Import-SWDiscovery -ComputerName $ComputerName -Integration ServiceNow +} +ForEach ($c in $ComputerName) { + #Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $c -Credential $IaaSAuto +} + +# Validate Solarwinds node creation +$Func = { + param($ComputerName) + $test = Get-SWNode -ComputerName $ComputerName + If ($test) { “Pass” } +} +ForEach ($c in $ComputerName) { + + Invoke-Command -ComputerName itdslrwnds.nd.gov -ScriptBlock $Func -ArgumentList $c -Credential $IaaSAuto +} + +Invoke-Command -ComputerName itdsccmp2.nd.gov -ScriptBlock { Get-Process } -Credential $PrvCred +#> + +$SCTaskNums = @" +SCTASK0173131 +SCTASK0173136 +"@ + +$SCTaskNums = ConvertTo-Array -MultiLineString $SCTaskNums +$SCTaskNums | ForEach-Object { Approve-ITDVMNewBuild -SCTaskNum $_ } + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.nuspec b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.nuspec new file mode 100644 index 0000000..0db755c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Infra-VMware.VirtualMachine + $VERSIONHERE$ + Zack Meier + Functions for VMware Virtual Machine tasks + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psd1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psd1 new file mode 100644 index 0000000..5995fcd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psd1 @@ -0,0 +1,133 @@ +# +# Module manifest for module 'ITD.Infra-VMware.VirtualMachine' +# +# Generated by: zmeier +# +# Generated on: 5/19/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.Infra-VMware.VirtualMachine.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + CompatiblePSEditions = 'Desktop', 'Core' + + + # ID used to uniquely identify this module + GUID = '0dc67c1a-d622-468c-880c-7b8001c44235' + + # Author of this module + Author = 'zmeier' + + # Company or vendor of this module + CompanyName = 'Unknown' + + # Copyright statement for this module + Copyright = '(c) zmeier. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'Functions for VMware Virtual Machine tasks' + + # 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 = @() + + # 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 = @("ITD.Infra-Passwordstate","ITD.Infra-Networking-Infoblox") + + } # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psm1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psm1 new file mode 100644 index 0000000..9abde6a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/ITD.Infra-VMware.VirtualMachine.psm1 @@ -0,0 +1,23 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Approve-ITDVMNewBuild.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Approve-ITDVMNewBuild.ps1 new file mode 100644 index 0000000..adc017f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Approve-ITDVMNewBuild.ps1 @@ -0,0 +1,140 @@ +<# +.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 Approve-ITDVMNewBuild { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $True)] + [string] + $SCTaskNum, + + [switch] + $CloseTask, + + [switch] + $NoTaskUpdates + ) + + begin { + + } + + process { + # get current user, SCTask, Ritm + $assignTo = Get-ServiceNowRecord -Table 'User' -Filter @('email', '-eq', ($env:username + "@nd.gov")) + + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + + $ComputerName = ($Ritm.CustomVariable | Where-Object Name -EQ host_name).Value + $OperatingSystem = ($Ritm.CustomVariable | Where-Object Name -EQ operating_system).Value + switch (($Ritm.CustomVariable | Where-Object Name -EQ target_platform).Value) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + # update short description + If ($NoTaskUpdates -eq $false) { + $shortdescription = "$target_platform $OperatingSystem VM Build for $ComputerName" + If ( ($RITM.CustomVariable | Where-Object Name -EQ dr_protection).Value -ne 'No DR') { + $shortdescription += ", with SRM protection" + } + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $shortdescription; assigned_to = $assignTo.name } + } + + # search for VM + switch (($Ritm.CustomVariable | Where-Object Name -EQ "target_platform").Value) { + 'azure' { + # update task close notes, task customer notes, and ritm customer notes + $CommentsToAdd = "Azure VM " + $ComputerName + " build completed. `n" + $CommentsForWorkNotes + } + 'vmware' { + $VM = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + switch (@($VM).count) { + { 0 -or $null } { + # no matches + Write-Error -Message "Zero VM matches found, ending script" -ErrorAction Stop + } + { $_ -ne 1 } { + # more than one match + Write-Error -Message " VM matches found, ending script" -ErrorAction Stop + } + { 1 } { + # add missing tags + switch (($Ritm.CustomVariable | Where-Object Name -EQ environment).Value){ + 'Development' { + $DtapString = 'Test' + } + 'Test' { + $DtapString = 'Test' + } + 'Production' { + $DtapString = 'Production' + } + } + + $SetITDVMwareTagsParams = @{ + ComputerName = $ComputerName; + #AppName = ($Ritm.CustomVariable | Where-Object Name -EQ application_name).Value; + Dtap = $DtapString; + #OperatingSystem = switch ( ($Ritm.CustomVariable | Where-Object Name -EQ target_os_version_windows).Value) { + # 'Windows Server 2019 Datacenter' { "Windows Server 2019 Standard (64-Bit)" } + # 'Windows Server 2022 Datacenter' { "Windows Server 2022 Standard (64-Bit)" } + #} + StartupPriority = ($Ritm.CustomVariable | Where-Object Name -EQ startup_priority).Value; + LicensingRestrictions = ($Ritm.CustomVariable | Where-Object Name -EQ licensing_restrictions).Value; + } + Set-ITDVMwareVMTag @SetITDVMwareTagsParams + + $AppNameTag = Get-TagAssignment -Entity $VM -Category AppName -ErrorAction SilentlyContinue + If ($AppNameTag) { + # move VM to VM folder that matches AppName tag + Write-Verbose -Message ("AppName tag " + $AppNameTag.Tag.Name + " found, attempting to move to AppName folder") + Move-ITDVMwareVMToAppNameFolder -Name $ComputerName + $CommentsForWorkNotes += "VM $ComputerName moved to AppName folder. " + } + Else { + Write-Warning "Review AppName tag for $ComputerName, required for backups" + } + + If (($Ritm.CustomVariable | Where-Object Name -EQ "dr_protection").value -ne 'No DR') { + Write-Warning "SCTask is not Closed. Review SRM Protection values manually" + $AutoCloseTask = $false + } + Else { + $AutoCloseTask = $true + } + + # update task close notes, task customer notes, and ritm customer notes + $CommentsToAdd = "VMware VM " + $ComputerName + " build completed. " + $CommentsForWorkNotes + } + } + } + } + + If ($NoTaskUpdates -eq $false) { + Update-ServiceNowRecord -ID $SCTask.number -Values @{work_notes = $CommentsToAdd; close_notes = $CommentsToAdd; } # enter comments into sctask + Update-ServiceNowRecord -ID $RitmNum -Values @{comments = $CommentsToAdd } + + If ($CloseTask -eq $True -or $AutoCloseTask -eq $True) { + Update-ServiceNowRecord -ID $SCTask.number -Values @{state = "Closed Complete" } + } + } + } + + end { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Compare-ITDVMwareVMTagsFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Compare-ITDVMwareVMTagsFromCmdb.ps1 new file mode 100644 index 0000000..fb3886e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Compare-ITDVMwareVMTagsFromCmdb.ps1 @@ -0,0 +1,137 @@ +<# +.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 Compare-ITDVMwareVMTagFromCmdb { + [CmdletBinding()] + param ( + [Parameter( + Mandatory = $true, + ValueFromPipeline = $true, + ParameterSetName = 'VMName' + )] + [string[]] + $VMName + ) + + begin { + #$Result = [System.Collections.ArrayList]@() + } + + process { + ForEach ($vname in $VMName) { + $HostName = $vname.split('.')[0] + Write-Verbose -Message "Looking up Cmdb Object named $HostName" + $Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName" + + If ($null -eq $Cmdb) { + Write-Warning -Message "No Cmdb Object found for $HostName" + Continue + } + + $VM = Get-VM -Name $vname | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + $OldTags = Get-TagAssignment -Entity $VM + + $VMCompare = [PSCustomObject]@{ + VMName = $vname; + DTAP = $null; + AppName = $null; + LicensingRestrictions = $null; + DRProtection = $null; + SRMRecoveryType = $null; + } + # DTAP + #If ($Cmdb.environment.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'DTAP' }).Tag.Name + If ($Cmdb.environment.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vname DTAP Tag to " + $Cmdb.environment.display_value) + #Set-ITDVMwareVMTag -ComputerName $vname -Dtap $Cmdb.environment.display_value + $VMCompare.DTAP = $false + } + Else { + $VMCompare.DTAP = $true + } + #} + + # AppName + #If ($Cmdb.u_nd_application_svc.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'AppName' }).Tag.Name + If ($Cmdb.u_nd_application_svc.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vname AppName Tag to " + $Cmdb.u_nd_application_svc.display_value) + #Set-ITDVMwareVMTag -ComputerName $vname -AppName $Cmdb.u_nd_application_svc.display_value + $VMCompare.AppName = $false + } + Else { + $VMCompare.AppName = $true + } + #} + + # Licensing Restrictions + #If ($Cmdb.u_nd_licensing_restrictions.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'LicensingRestrictions' }).Tag.Name + If ($Cmdb.u_nd_licensing_restrictions.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vname Licensing Restrictions Tag to " + $Cmdb.u_nd_licensing_restrictions.display_value) + #Set-ITDVMwareVMTag -ComputerName $vname -LicensingRestrictions $Cmdb.u_nd_licensing_restrictions.display_value + $VMCompare.LicensingRestrictions = $false + } + Else { + $VMCompare.LicensingRestrictions = $true + } + #} + + # startup priority TBD + # startup priority is not in Cmdb + + # SRM Recovery Type + #If ($Cmdb.u_srm_recovery_type.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'SRM Recovery Type' }).Tag.Name + If ($Cmdb.u_srm_recovery_type.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vname SRM Recovery Type Tag to " + $Cmdb.u_srm_recovery_type.display_value) + #Set-ITDVMwareVMTag -ComputerName $vname -SRMRecoveryType $Cmdb.u_srm_recovery_type.display_value + $VMCompare.SRMRecoveryType = $false + } + Else { + $VMCompare.SRMRecoveryType = $true + } + #} Else { + #$TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'SRM Recovery Type' }).Tag.Name + #If ($null -ne $TagAssignmentValue) { + #Write-Verbose -Message ("Setting $vname SRM Recovery Type Tag to " + $null) + #$VMCompare.SRMRecoveryType = $false + #} + #Else { + #$VMCompare.SRMRecoveryType = $true + #} + #} + # + # DR Protection + #If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") ) { + #-replace "VMware: " -replace "RPO", "VR RPO" + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'DR Protection' }).Tag.Name + If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vname DR Protection Tag to " + ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: ") ) + #Set-ITDVMwareVMTag -ComputerName $vname -DRProtection ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") + $VMCompare.DRProtection = $false + } + Else { + $VMCompare.DRProtection = $true + } + #} + Write-Output $VMCompare + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMAppNameTag.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMAppNameTag.ps1 new file mode 100644 index 0000000..3c9a48b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMAppNameTag.ps1 @@ -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-ITDVMwareVMAppNameTag { + [CmdletBinding()] + param ( + + ) + + begin { + $ViServer = $global:defaultviservers | sort-object Name | select -first 1 + } + + process { + $AppNameTags = Get-Tag -Category AppName -Server $ViServer.Name + } + + end { + $AppNameTags + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMHardening.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMHardening.ps1 new file mode 100644 index 0000000..9c430b4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMHardening.ps1 @@ -0,0 +1,63 @@ +<# +.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-ITDVMwareVMHardening { + [CmdletBinding()] + param( + [string] + $Name + ) + Begin { + + } + Process { + $SettingName = @( + "tools.setInfo.sizeLimit", + "isolation.device.edit.disable", + "isolation.device.connectable.disable", + "isolation.tools.copy.disable", + "isolation.tools.dnd.disable", + "isolation.tools.setGUIOptions.enable", + "isolation.tools.paste.disable", + "isolation.tools.diskShrink.disable", + "isolation.tools.diskWiper.disable", + "log.keepOld", + "log.rotateSize" + ) + $Result = [System.Collections.ArrayList]@() + ForEach ($n in $Name) { + $VM = Get-VM -Name $n | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + $GetAdvSetting = Get-AdvancedSetting -Entity $VM -Name $SettingName | select Entity, Name, Value + $obj = [PSCustomObject]@{ + 'Entity' = $VM.Name + 'Uid' = $VM.Uid.split('@')[1].split(':')[0] + "tools.setInfo.sizeLimit" = ($GetAdvSetting | Where-Object Name -EQ 'tools.setInfo.sizeLimit').Value + "isolation.device.edit.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.edit.disable').Value + "isolation.device.connectable.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.connectable.disable').Value + "isolation.tools.copy.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.copy.disable').Value + "isolation.tools.dnd.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.dnd.disable').Value + "isolation.tools.setGUIOptions.enable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.setGUIOptions.enable').Value + "isolation.tools.paste.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.paste.disable').Value + "isolation.tools.diskShrink.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskShrink.disable').Value + "isolation.tools.diskWiper.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskWiper.disable').Value + "log.keepOld" = ($GetAdvSetting | Where-Object Name -EQ 'log.keepOld').Value + "log.rotateSize" = ($GetAdvSetting | Where-Object Name -EQ 'log.rotateSize').Value + } + $Result.Add($obj) + } + } + End { + Write-Output $Result + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMRPO.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMRPO.ps1 new file mode 100644 index 0000000..f191e29 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMRPO.ps1 @@ -0,0 +1,40 @@ +<# +.Synopsis + Retreives list of all VMs, and lists their corresponding vSphere Replication RPO settings, if applicable. +.DESCRIPTION + Long description +.EXAMPLE + Get-ITDVMwareRPO +#> +function Get-ITDVMwareVMRPO { + [CmdletBinding()] + Param + ( + ) + + Begin { + + } + Process { + $VMs = Get-VM -Name itddohslimsp2.nd.gov | Where-Object PowerState -EQ PoweredOn + $result = @() + ForEach ($VM in $VMs) { + Write-Verbose $VM.Name + $RPOMinutes = ($VM.ExtensionData.Config.extraconfig | Where-Object key -EQ hbr_filter.rpo).Value + $DatastoreTag = ($VM | Get-TagAssignment -Category "VR Datastores").Tag.Name + $Cluster = ($VM | Get-Cluster).Name + + $obj = [PSCustomObject]@{ + 'Name' = $VM.Name; + 'Cluster' = $Cluster; + 'Datastore' = $DatastoreTag; + 'RPO' = $RPOMinutes; + } + Write-Warning $obj + $result += $obj + } + } + End { + Write-Output $result + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMTagReport.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMTagReport.ps1 new file mode 100644 index 0000000..cfd86dd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMTagReport.ps1 @@ -0,0 +1,122 @@ +<# +.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-ITDVMwareVMTagReport { + [CmdletBinding()] + param ( + [Parameter( + ValueFromPipeline = $true, + ParameterSetName = 'VMName' + )] + [string] + $VMName + ) + + begin { + #$Result = [System.Collections.ArrayList]@() + } + + process { + If ($PSBoundParameters.ContainsKey('VMName')) { + # do nothing + } + Else { + $VMName = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + } + + ForEach ($vn in $VMName) { + $HostName = $vn.split('.')[0] + Write-Verbose -Message "Looking up Cmdb Object named $HostName" + $Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName" + $VM = Get-VM -Name $vn | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + $OldTags = Get-TagAssignment -Entity $VM + + $obj = [PSCustomObject]@{ + VMName = $vn; + DTAP = $null; + AppName = $null; + LicensingRestrictions = $null; + DRProtection = $null; + SRMRecoveryType = $null; + } + # DTAP + If ($Cmdb.environment.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'DTAP' }).Tag.Name + If ($Cmdb.environment.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vn DTAP Tag to " + $Cmdb.environment.display_value) + $obj.DTAP = $false + } + Else { + $obj.DTAP = $true + } + } + + # AppName + If ($Cmdb.u_nd_application_svc.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'AppName' }).Tag.Name + If ($Cmdb.u_nd_application_svc.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vn AppName Tag to " + $Cmdb.u_nd_application_svc.display_value) + $obj.AppName = $false + } + Else { + $obj.AppName = $true + } + } + + # Licensing Restrictions + If ($Cmdb.u_nd_licensing_restrictions.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'LicensingRestrictions' }).Tag.Name + If ($Cmdb.u_nd_licensing_restrictions.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vn Licensing Restrictions Tag to " + $Cmdb.u_nd_licensing_restrictions.display_value) + $obj.LicensingRestrictions = $false + } + Else { + $obj.LicensingRestrictions = $true + } + } + + # startup priority TBD + # startup priority is not in Cmdb + + # SRM Recovery Type + If ($Cmdb.u_srm_recovery_type.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'SRM Recovery Type' }).Tag.Name + If ($Cmdb.u_srm_recovery_type.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vn SRM Recovery Type Tag to " + $Cmdb.u_srm_recovery_type.display_value) + $obj.SRMRecoveryType = $false + } + Else { + $obj.SRMRecoveryType = $true + } + } + # + # DR Protection + If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") ) { + #-replace "VMware: " -replace "RPO", "VR RPO" + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'DR Protection' }).Tag.Name + If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $vn DR Protection Tag to " + ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: ") ) + $obj.DRProtection = $false + } + Else { + $obj.DRProtection = $true + } + } + } + } + + end { + Write-Output $obj + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMToolsReport.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMToolsReport.ps1 new file mode 100644 index 0000000..48ffffa --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Get-ITDVMwareVMToolsReport.ps1 @@ -0,0 +1,71 @@ +<# +.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-ITDVMwareVMToolsReport { + [CmdletBinding()] + param ( + [string[]] + $VMName, + + [ValidateSet("Windows", "RHEL", "Other")] + [string] + $GuestOS + ) + + begin { + + } + + process { + If ($PSBoundParameters.ContainsKey('VMName')) { + $AllVMs = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "vCLS*" } + } + else { + $AllVMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "vCLS*" } + } + + If ($PSBoundParameters.ContainsKey('GuestOS') ) { + switch ($GuestOS) { + "Windows" { + $AllVMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestId -like "*windows*" } + } + "RHEL" { + $AllVMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestId -like "*rhel*" } + } + "Other" { + $AllVMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestId -notlike "*rhel*" -and $_.ExtensionData.Guest.GuestId -notlike "*windows*" } + } + Default { + Write-Error "Invalid GuestOS specified. Use 'Windows' or 'RHEL'." + return + } + } + } + + ForEach ($VM in $AllVMs) { + $obj = [PSCustomObject]@{ + Name = $VM.Name; + PowerState = $VM.PowerState; + GuestOS = $VM.ExtensionData.Guest.GuestId; + ToolsVersion = $VM.ExtensionData.Config.Tools.ToolsVersion; + ToolsUpgradePolicy = $VM.ExtensionData.Config.Tools.ToolsUpgradePolicy + } + Write-Output $obj + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Move-ITDVMwareVMToAppNameFolder.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Move-ITDVMwareVMToAppNameFolder.ps1 new file mode 100644 index 0000000..134277b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Move-ITDVMwareVMToAppNameFolder.ps1 @@ -0,0 +1,59 @@ +<# +.SYNOPSIS + Move Virtual Machines to the correct folder based on the AppName tag +.DESCRIPTION + Move Virtual Machines to the correct folder based on the AppName tag +.NOTES + +.LINK + +.EXAMPLE + Move-ITDVMwareVMToAppNameFolder -VMName itdservername.nd.gov +#> + +function Move-ITDVMwareVMToAppNameFolder { + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] + [string[]] + $VMName + ) + + begin { + } + + process { + Write-Verbose -Message "Gathering Virtual Machine information" + $VMs = Get-VM -Name $VMName | Select-Object Name, PowerState, Folder, @{n = 'VIServer'; e = { $_.Uid.split('@')[1].split(':')[0] } }, @{n = 'AppName'; e = { (Get-TagAssignment -Category AppName -Entity $_).Tag.Name } }, @{n = 'Datacenter'; e = { ($_ | Get-Datacenter).Name } } | Sort-Object Name + + ForEach ($VM in $VMs) { + Write-Verbose -Message ("Start " + $VM.Name) + + $NewFolder = $null + $Owner = $VM.AppName.split('-')[0] + + Write-Verbose ($VM.Name + ": current folder is " + $VM.Folder.Name) + Write-Verbose ($VM.Name + ": current appname is " + $VM.AppName) + + If ($VM.Folder.Name -ne $VM.AppName) { + If ($VM.AppName) { + Write-Verbose ($VM.Name + ": Folder and AppName are different!!! moving VM to folder " + $VM.AppName) + If (!(Get-Datacenter $VM.Datacenter | Get-Folder -Name $VM.AppName -Server $VM.VIServer -ErrorAction SilentlyContinue)) { + New-Folder -Name $VM.AppName -Location (Get-Datacenter $VM.Datacenter | Get-Folder -Type VM -Name $Owner -Server $VM.VIServer) + } + + $NewFolder = Get-Datacenter $VM.Datacenter | Get-Folder $VM.AppName -Server $VM.VIServer + Move-VM -VM $VM.Name -InventoryLocation $NewFolder -Destination (Get-VM $VM.Name -Server $VM.VIServer).VMHost + } + Else { + + } + } + } + + } + + end { + } +} diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMSNowRitm.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMSNowRitm.ps1 new file mode 100644 index 0000000..97e3e1e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMSNowRitm.ps1 @@ -0,0 +1,282 @@ +<# +.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 + $NewITDVMSNowRitmParams = @{ + RequestType = "New"; + ComputerName = "itdzmtest100.nd.gov"; + SysadminEmail = "zmeier@nd.gov"; + CustomerRitm = "RITM0145886"; + Environment = "Test"; + AppName = "Infra-VMware"; + Comments = "New VM for VMware sandbox, see RITM0145886 for details"; + OperatingSystem = "Windows"; + TargetOSVersion = "Windows Server 2022 Datacenter"; + TargetPlatform = "VMware"; + NumCpu = 1; + MemoryGB = 4; + Disk1GB = 50; + Disk2GB = 5; + CIDR = '10.11.12.0/23'; + Datacenter = 'Bismarck'; + LicensingRestrictions = 'No Licensing Restrictions'; + AgencyPrefix = 'ITD'; + SupportHours = 'All Day Every Day'; + DRProtection = 'No DR'; + StartupPriority = 5; + } + New-ITDVMSNowRitm @NewITDVMSNowRitmParams +.EXAMPLE + New-ITDVMSNowRitm -ImportCsv "C:\temp\NewITDVMSnowRitm.csv" +#> + +function New-ITDVMSNowRitm { + [CmdletBinding()] + param ( + [Parameter(ParameterSetName = 'Csv')] + [string] + $ImportCsv, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [ValidateSet('New', 'Upgrade/Code Deployment', 'Removal', 'Other')] + [string] + $RequestType, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [string] + $ComputerName, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [string] + $SysadminEmail, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [string] + $Comments, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [ValidateSet('Production', 'Test')] + [string] + $Environment, + + [Parameter(ParameterSetName = 'Single', Mandatory = $true)] + [string] + $AppName, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet('Linux', 'Windows')] + [string] + $OperatingSystem, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet( + 'Windows Server 2019 Datacenter', + 'Windows Server 2022 Datacenter' + )] + [string] + $TargetOSVersion, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet('VMware', 'Azure')] + $TargetPlatform, + + [Parameter(ParameterSetName = 'Single')] + [int] + $NumCpu, + + [Parameter(ParameterSetName = 'Single')] + [int] + $MemoryGB, + + [Parameter(ParameterSetName = 'Single')] + [int] + $Disk1GB, + + [Parameter(ParameterSetName = 'Single')] + [int] + $Disk2GB, + + [Parameter(ParameterSetName = 'Single')] + [string] + $CIDR, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet('Bismarck', 'Mandan')] + [string] + $Datacenter, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet( + 'No Licensing Restrictions', + 'Microsoft SharePoint Server', + 'Microsoft SharePoint Server (Academic)', + 'Microsoft SQL Developer', + 'Microsoft SQL MSDN', + 'Microsoft SQL Standard', + 'Microsoft SQL Standard (Academic)', + 'Microsoft SQL Standard (Vendor Provided)', + 'Microsoft SQL Enterprise', + 'Microsoft SQL Enterprise (Academic)', + 'IBM Websphere', + 'IBM ODM', + 'Oracle Standard Edition', + 'Oracle Standard Edition One', + 'Powerschool' + )] + [string] + $LicensingRestrictions, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet('ITD', 'DHS', 'DOT')] + [string] + $AgencyPrefix, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet('All Day Every Day', 'All Week 500 to 2300', 'Weekdays 700 1800')] + [string] + $SupportHours, + + [Parameter(ParameterSetName = 'Single')] + [ValidateSet( + 'No DR', + 'VMWare: ABR', + 'VMWARE: RPO 0:15', + 'VMWARE: RPO 0:30', + 'VMWARE: RPO 1:00', + 'VMWARE: RPO 2:00', + 'VMWARE: RPO 4:00', + 'VMWARE: RPO 8:00')] + [string] + $DRProtection, + + [Parameter(ParameterSetName = 'Single')] + [ValidateRange(1, 5)] + [int] + $StartupPriority + ) + + begin { + + } + + process { + switch ($PSCmdlet.ParameterSetName) { + 'Csv' { + $Csv = Import-Csv $ImportCsv + ForEach ($item in $csv) { + $NewITDVMSNowRitmParams = @{ + RequestType = $item.RequestType + ComputerName = $item.ComputerName + SysadminEmail = $item.SysadminEmail + Environment = $item.Environment + AppName = $item.AppName + Comments = $item.Comments + OperatingSystem = $item.OperatingSystem + TargetOSVersion = $item.TargetOSVersion + TargetPlatform = $item.TargetPlatform + NumCpu = $item.NumCpu + MemoryGB = $item.MemoryGB + Disk1GB = $item.Disk1GB + Disk2GB = $item.Disk2GB + CIDR = $item.CIDR + Datacenter = $item.Datacenter + LicensingRestrictions = $item.LicensingRestrictions + AgencyPrefix = $item.AgencyPrefix + SupportHours = $item.SupportHours + DRProtection = $item.DRProtection + StartupPriority = $item.StartupPriority + } + New-ITDVMSNowRitm @NewITDVMSNowRitmParams + } + } + 'Single' { + Write-Verbose -Message ("Start " + $ComputerName) + # determine lookup fields + + switch ($PSBoundParameters.Keys) { + CIDR { + $cidr_block = Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -Filter "name=$CIDR" + If ($null -eq $cidr_block) { Write-Error -Message "CIDR is invalid" -ErrorAction Stop } + } + AgencyPrefix { + switch ($AgencyPrefix) { + 'DHS' { $AgencyNum = '325.0' } + 'DOT' { $AgencyNum = '801.0' } + 'ITD' { $AgencyNum = '112.0' } + } + $Agency = Get-ITDServiceNowRecord -Table 'cmn_department' -Filter "id=$AgencyNum" + } + AppName { + $application_info = Get-ITDServiceNowRecord -Table cmdb_ci_service -Filter ("name=$AppName") + } + # send ints as strings + NumCpu { + [string]$NumCpuStr = $NumCpu.ToString() + } + MemoryGB { + [string]$MemoryGBStr = $MemoryGB.ToString() + } + Disk1GB { + [string]$Disk1GBStr = $Disk1GB.ToString() + } + Disk2GB{ + [string]$Disk2GBStr = $Disk2GB.ToString() + } + } + + $team_lead_sysid = (Get-ITDServiceNowUser -Email $RequestedForEmail).manager.value + + $NewITDServiceNowServiceCatalogRequestParams = @{ # review and update all of these too + CategoryItemName = "Application Server"; + RequestedForEmail = $SysadminEmail; + Values = @{ + request_type = $RequestType; + application_name = $AppName; + environment = $Environment; + require_hosting_quote = 'No'; + server_name = $ComputerName; + add_change_disaster_recovery = 'No'; + additional_comments = $Comments; + #### + vm_work_needed = 'Yes'; + host_name = $ComputerName; + server_type = 'Virtual'; + operating_system = $OperatingSystem; + target_os_version_windows = $TargetOSVersion; + target_platform = $TargetPlatform; + processors = $NumCpuStr; + memory_gb = $MemoryGBStr; + disk_1_os = $Disk1GBStr; + disk_2_swap_disk = $Disk2GBStr; + data_center = $Datacenter; + licensing_restrictions = $LicensingRestrictions; + support_hours = $SupportHours; + dr_protection = $DRProtection; + startup_priority = $StartupPriority; + + # lookups + cidr_block = $cidr_block.sys_id; + agency_name = $agency.sys_id; + team_lead = $team_lead.sys_id; + application_info = $application_info.sys_id; + + }; + } + New-ITDServiceNowServiceCatalogRequest @NewITDServiceNowServiceCatalogRequestParams + + #$NewITDServiceNowServiceCatalogRequestParams + Write-Verbose -Message ("End " + $ComputerName) + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMwareSharePointVMRecord.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMwareSharePointVMRecord.ps1 new file mode 100644 index 0000000..2558f28 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/New-ITDVMwareSharePointVMRecord.ps1 @@ -0,0 +1,193 @@ +<# +.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 + $params = @{ + HostName = "itdzmtest999.nd.gov"; + LicensingRestrictions = "No Licensing Restrictions"; + DataCenter = 'Bismarck'; + Environment = 'Test'; + StartupPriority = '5'; + OperatingSystem = 'Windows Server 2022 Datacenter (64-Bit)' + DR_Protection = 'None'; + CPU = 1; + MemoryGB = 4; + Disk1 = 50; + Disk2 = 2; + Disk3 = 3; + + } + + New-ITDVMwareSharePointVMRecord @params +#> + +function New-ITDVMwareSharePointVMRecord { + [CmdletBinding()] + param ( + [string] + $HostName, + + [string] + $ReplacesVM, + + [string] + $LicensingRestrictions, + + <#[string] + $AgencyName,#> + + [string] + $SupportHours, + + [string] + $DataCenter, + + [string] + $Environment, + + [int] + $StartupPriority, + + [string] + $DR_Protection, + + [string] + $OperatingSystem, + + [int] + $CPU, + + [int] + $MemoryGB, + + [string] + $CIDRBlock, + + [int] + $Disk1, + + [int] + $Disk2, + + [int] + $Disk3, + + [int] + $Disk4, + + [int] + $Disk5, + + [int] + $Disk6, + + [int] + $Disk7, + + [int] + $Disk8, + + [int] + $Disk9, + + [int] + $Disk10, + + [int] + $Disk11, + + [int] + $Disk12, + + [int] + $Disk13, + + [int] + $Disk14, + + [int] + $Disk15, + + [int] + $Disk16 + ) + + begin { + $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" + $InvokeWebRequestParams = @{ + Uri = $UrlContextInfo; + Method = "Post"; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials + $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams + $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue + + $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Guests')" + $InvokeWebRequestParams = @{ + Uri = $UrlList; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials + $List = Invoke-RestMethod @InvokeWebRequestParams + $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName + + $UrlListItems = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Guests')/items" + + $header = @{ + "accept" = "application/json;odata=verbose" + "X-RequestDigest" = $RequestDigest + } + } + + process { + [PSCustomObject]$NewRecord = @{ + "__metadata" = @{type = $ListItemEntityTypeFullName } + Title = $HostName + } + write-host $PSBoundParameters + switch($PSBoundParameters.Keys){ + # '' {$NewRecord += @{ = }} + 'LicensingRestrictions' {$NewRecord += @{LicensingRestrictions = $LicensingRestrictions}} + 'DataCenter' {$NewRecord += @{DataCenter = $DataCenter}} + 'Environment' {$NewRecord += @{Environment = $Environment}} + 'StartupPriority' {$NewRecord += @{StartupPriority = [string]$StartupPriority}} + 'OperatingSystem' {$NewRecord += @{OS = $OperatingSystem}} + 'DR_Protection' {$NewRecord += @{DR_Protection = $DR_Protection}} + 'CPU' {$NewRecord += @{Processors = $CPU}} + 'MemoryGB' {$NewRecord += @{RAM = $MemoryGB}} + 'Disk1' {$NewRecord += @{Disk_x0020_C_x003a_ = $Disk1}} + 'Disk2' {$NewRecord += @{Disk2_x002d_SwapDisk = $Disk2}} + 'Disk3' {$NewRecord += @{Disk_x0020_D_x003a_ = $Disk3}} + } + + $body = $NewRecord | ConvertTo-Json + + $InvokeWebRequestParams = @{ + Uri = $UrlListItems; + Method = "Post"; + Body = $body; + ContentType = "application/json;odata=verbose"; + Headers = $header; + UseBasicParsing = $true; + } + If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } } + Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } } + #Invoke-RestMethod -Method Post -Uri $UrlListItems -Body $body -ContentType "application/json;odata=verbose" -Headers $header -UseDefaultCredentials + Invoke-RestMethod @InvokeWebRequestParams + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDLinuxServer.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDLinuxServer.ps1 new file mode 100644 index 0000000..30148fd --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDLinuxServer.ps1 @@ -0,0 +1,80 @@ +<# +.SYNOPSIS + Updates ServiceNow SCTask after a Linux VM is deleted +.DESCRIPTION + Updates ServiceNow SCTask after a Linux VM is deleted +.NOTES + Information or caveats about the function e.g. 'This function is not supported in Linux' +.EXAMPLE + Test-MyTestFunction -Verbose + Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines +#> + +function Remove-ITDLinuxServerMissingCmdb { + [CmdletBinding()] + param ( + [string] + $SCTaskNum, + + [string] + $ComputerName + ) + + begin { + + } + + process { + # get current user, SCTask, Ritm, custom variables + $assignTo = Get-ServiceNowRecord -Table 'User' -Filter @('email', '-eq', ($env:username + "@nd.gov")) + + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + [string]$SNHostName = ($RITM.CustomVariable | Where-Object Name -EQ server_name).Value + + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = "VMware VM Removal for $SNHostName"; assigned_to = $assignTo.name } + + If ($ComputerName -ne $SNHostName) { + # false is good + Write-Error -Message ("ComputerName entered in parameters does not match Host Name field in " + $SCTaskNum) -ErrorAction Stop + } + + $VMs = Get-VM -Name $ComputerName -ErrorAction SilentlyContinue | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + switch (@($VMs).count) { + { 0 } { + Write-Warning "$ComputerName not found in vCenter... is it Azure?" + } + { $_ -gt 1 } { + Write-Warning '-gt 1' + Write-Error -Message ("Multiple virtual machines with name $ComputerName were found. Are there SRM placeholders? If so, unconfigure SRM and run this again. If there are no placeholders, confirm the virtual machine name.") -ErrorAction Stop + } + 1 { + Write-Warning '1' + $TagAssignment = Get-TagAssignment -Entity $VMs + $vCenterInfo = $TagAssignment | select Tag, Entity | ConvertTo-Json -Depth 1 + If ($VMs.PowerState -eq 'PoweredOn') { + #$VMs | Stop-VMGuest -Confirm:$false + $VMs | Stop-VM -Confirm:$false + } + + If ($vCenterInfo) { + Update-ServiceNowRecord -ID $SCTaskNum -Values @{work_notes = ("vCenter Information: `n " + $vCenterInfo) } # enter work_notes into sctask + } + } + } + + + $CommentsForWorkNotes = ("VMware VM $SNHostName has been deleted. ") + #$HardwareRemovalDescription = ("$SNHostName hardware is ready for removal.") + + # if no errors, close sctask + #$CommentsForWorkNotes += "VMware: Virtual machine named $ComputerName deleted." + Update-ServiceNowRecord -ID $SCTaskNum -Values @{work_notes = $CommentsForWorkNotes; state = "Closed Complete"; close_notes = $CommentsForWorkNotes} + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDVMviaSNowTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDVMviaSNowTask.ps1 new file mode 100644 index 0000000..7e32c8e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Remove-ITDVMviaSNowTask.ps1 @@ -0,0 +1,130 @@ +<# +.SYNOPSIS + Updates ServiceNow SCTask after a Linux VM is deleted +.DESCRIPTION + Updates ServiceNow SCTask after a Linux VM is deleted +.NOTES + Information or caveats about the function e.g. 'This function is not supported in Linux' +.EXAMPLE + Test-MyTestFunction -Verbose + Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines +#> + +function Remove-ITDVMviaSNowTask { + [CmdletBinding()] + param ( + [string] + $SCTaskNum, + + [string] + $ComputerName + ) + + begin { + + } + + process { + # get current user, SCTask, Ritm, custom variables + switch ($env:username) { + 'svcitdiaasauto' { + $assignTo = Get-ITDServiceNowUser -Username svcvmwareadm + } + Default { + $assignTo = Get-ITDServiceNowUser -Username $Env:username + } + } + + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + + Write-Verbose -Message "Retrieve $RitmNum and its VariableSet" + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum -IncludeVariableSet -ErrorAction Stop + + ###### the name in the $ComputerName parameter must match a name in the form to continue + Write-Verbose -Message "Looking for a match of `$ComputerName $ComputerName and one of the rows' `$TempCi.FQDN.display_value" + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($ComputerName -eq $TempCi.FQDN.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + If ($MatchFound -eq $false) { + Write-Error -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -ErrorAction Stop + } + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTask.number.display_value -Values @{assigned_to = $assignTo.name } + + $FQDN = $Ci.fqdn.display_value + + switch ( $Ci.model_id.display_value ) { + { $_ -like "*VMware*" } { + $hardware_platform = "VMware"; + $hardware_type = 'Virtual Machine' + + $VMs = Get-VM -Name $FQDN -ErrorAction SilentlyContinue | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + switch ( @($VMs).count ) { + { 0 } { + Write-Warning "$FQDN not found in vCenter... is it Azure? Or does it not exist?" + } + { $_ -gt 1 } { + Write-Verbose -Message "Multiple virtual machines with name $FQDN were found." + Write-Error -Message ("Multiple virtual machines with name $FQDN were found. Are there SRM placeholders? If so, unconfigure SRM and run this again. If there are no placeholders, confirm the virtual machine name.") -ErrorAction Stop + } + 1 { + Write-Verbose -Message "One virtual machine with name $FQDN were found." + + If ($VMs.PowerState -eq 'PoweredOff') { + # do nothing + } + Else { + Write-Error -Message "VMware VM $FQDN is still powered on. " + } + + $TagAssignment = Get-TagAssignment -Entity $VMs + $vCenterInfo = $TagAssignment | select Tag, Entity | ConvertTo-Json -Depth 1 + If ($VMs.PowerState -eq 'PoweredOn') { + Write-Verbose -Message "Power off VMware VM $FQDN" + $CommentsForWorkNotes += ("`nVMware: VM $FQDN has been powered off. ") + $VMs | Stop-VM -Confirm:$false + } + + #If ($vCenterInfo) { + # enter work_notes into sctask + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = ("vCenter Information: `n " + $vCenterInfo) + } + #} + } + } + } + { $_ -like "*Microsoft Virtual Machine*" } { + $hardware_platform = "Azure"; + $hardware_type = 'Virtual Machine' + } + { $_ -like "*HP*" } { + $hardware_platform = 'HPE'; + $hardware_type = 'Physical' + } + default { $hardware_platform = 'Other' } + } + + $CommentsForWorkNotes = ("$hardware_platform $hardware_type $FQDN has been deleted. ") + + # Set SharePoint status to "Delete" + #Set-ITDVMwareSharePointVMRecord -Title $FQDN -Status Delete -Verbose + + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{ + work_notes = $CommentsForWorkNotes; + state = 'Closed Complete'; + close_notes = $CommentsForWorkNotes + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMHardening.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMHardening.ps1 new file mode 100644 index 0000000..a601c5a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMHardening.ps1 @@ -0,0 +1,117 @@ +<# +.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 Set-ITDVMwareVMHardening { + [CmdletBinding()] + param( + [string[]] + $Name + ) + Begin { + + } + Process { + If ($Name) { + $VMs = Get-VM -Name $Name | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + } + Else { + $VMs = Get-VM -Name $Name | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } + } + + $SettingName = @( + "tools.setInfo.sizeLimit", + "isolation.device.edit.disable", + "isolation.device.connectable.disable", + "isolation.tools.copy.disable", + "isolation.tools.dnd.disable", + "isolation.tools.setGUIOptions.enable", + "isolation.tools.paste.disable", + "isolation.tools.diskShrink.disable", + "isolation.tools.diskWiper.disable", + "log.keepOld", + "log.rotateSize" + ) + + $Result = [System.Collections.ArrayList]@() + ForEach ($VM in $VMs) { + $GetAdvSetting = Get-AdvancedSetting -Entity $VM -Name $SettingName | select Entity, Name, Value + $obj = [PSCustomObject]@{ + 'Entity' = $VM.Name + 'Uid' = $VM.Uid.split('@')[1].split(':')[0] + "tools.setInfo.sizeLimit" = ($GetAdvSetting | Where-Object Name -EQ 'tools.setInfo.sizeLimit').Value + "isolation.device.edit.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.edit.disable').Value + "isolation.device.connectable.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.connectable.disable').Value + "isolation.tools.copy.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.copy.disable').Value + "isolation.tools.dnd.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.dnd.disable').Value + "isolation.tools.setGUIOptions.enable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.setGUIOptions.enable').Value + "isolation.tools.paste.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.paste.disable').Value + "isolation.tools.diskShrink.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskShrink.disable').Value + "isolation.tools.diskWiper.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskWiper.disable').Value + "log.keepOld" = ($GetAdvSetting | Where-Object Name -EQ 'log.keepOld').Value + "log.rotateSize" = ($GetAdvSetting | Where-Object Name -EQ 'log.rotateSize').Value + } + $Result.Add($obj) + } + + $Result + + # remediate VMs + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'tools.setInfo.sizeLimit' -ne 1048576 }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'tools.setInfo.sizeLimit' -Value '1048576' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.edit.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.device.edit.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.connectable.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.device.connectable.disable' -Value TRUE -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.copy.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.copy.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.dnd.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.dnd.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.setGUIOptions.enable' -ne "FALSE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.setGUIOptions.enable' -Value 'FALSE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.paste.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.paste.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskShrink.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.diskShrink.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskWiper.disable' -ne "TRUE" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'isolation.tools.diskWiper.disable' -Value 'TRUE' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.keepOld' -ne "10" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'log.keepOld' -Value '10' -Confirm:$false -Force:$true + } + + ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.rotateSize' -ne "1024000" }) ) { + Get-VM -Name $VM.Entity -Server $VM.Uid | New-AdvancedSetting -Name 'log.rotateSize' -Value '10' -Confirm:$false -Force:$true + } + } + End { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTag.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTag.ps1 new file mode 100644 index 0000000..8df7814 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTag.ps1 @@ -0,0 +1,330 @@ +<# +.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 Set-ITDVMwareVMTag { + [CmdletBinding()] + param + ( + [string] + $ComputerName, + + [string] + $AppName, + + [string] + $Dtap, + + <#[string] + $OperatingSystem,#> + + [string] + $StartupPriority, + + [string] + $LicensingRestrictions, + + [string] + $DRProtection, + + [string] + $SRMRecoveryType + ) + + begin { + } + + process { + + $VMs = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + If ($VMs) { + ForEach ($VM in $VMs) { + #AppName Tag + If ($AppName) { + Write-Verbose ($VM.Name + ": AppName Tag Start") + $OldTag = Get-TagAssignment -Category AppName -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $AppName + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " AppName old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category AppName -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer)# + } + Write-Verbose ($VM.Name + ": AppName Tag End") + } + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + #DTAP Tag + If ($DTAP) { + Write-Verbose ($VM.Name + ": DTAP Tag Start") + $OldTag = Get-TagAssignment -Category DTAP -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $DTAP + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " DTAP old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category DTAP -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + Write-Verbose ($VM.Name + ": DTAP Tag End") + } + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + #Startup Priority + If ($StartupPriority) { + Write-Verbose ($VM.Name + ": StartupPriority Tag Start") + $OldTag = Get-TagAssignment -Category 'StartupPriority' -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $StartupPriority + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " StartupPriority old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'StartupPriority' -Name $NewTagName) -Server $VIServer + + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + Write-Verbose ($VM.Name + ": StartupPriority Tag End") + } + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + <# OS Tag + If ($OperatingSystem) { + Write-Verbose ($VM.Name + ": OS Tag Start") + $OldTag = Get-TagAssignment -Category "Operating System" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $OperatingSystem + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " OS old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'Operating System' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + + + + Write-Verbose ($VM.Name + ": OS Tag End") + } + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + #> + + # Licensing Tag + If ($LicensingRestrictions) { + Write-Verbose ($VM.Name + ": Licensing Restrictions Tag Start") + $OldTag = Get-TagAssignment -Category "LicensingRestrictions" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $LicensingRestrictions + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " Licensing old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'LicensingRestrictions' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + Write-Verbose ($VM.Name + ": Licensing Tag End") + } + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + # SRM Recovery Type Tag + If ($SRMRecoveryType) { + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag Start") + $OldTag = Get-TagAssignment -Category "SRM Recovery Type" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $SRMRecoveryType + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " SRM Recovery Type old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'SRM Recovery Type' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag End") + } + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + # DR Protection + If ($DRProtection) { + Write-Verbose ($VM.Name + ": DR Protection Tag Start") + $OldTag = Get-TagAssignment -Category "DR Protection" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $DRProtection + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " DR Protection old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'DR Protection' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + Write-Verbose ($VM.Name + ": DR Protection Tag End") + } + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + + } + + <# SRM Recovery Type Tags + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag Start") + $OldTag = Get-TagAssignment -Category "SRM Recovery Type" -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + If ($VM.ExtensionData.summary.config.ManagedBy.Type -eq "placeholderVm" ) { + #If VM is placeholder + $NewTagName = "Placeholder" + } + Else { + $NewTagName = $SPItem.SRM_RecoveryVMtype + } + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " SRM Recovery Type old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'SRM Recovery Type' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + } + + Write-Verbose ($VM.Name + ": SRM Recovery Type Tag End")#> + + $OldTag = $null + $VIServer = $null + $OldTagName = $null + $NewTagName = $null + + <#VR RPO Tag + Write-Verbose ($VM.Name + ": SRM Tag Start") + $OldTag = Get-TagAssignment -Category 'VR RPO' -Entity $VM + $VIServer = $VM.Uid.split('@')[1].split(':')[0] + $OldTagName = $OldTag.tag.name + $NewTagName = $SPItem.DR_Protection -replace "VMware: " + + If ($OldTagName -ne $NewTagName) { + Write-Verbose ($VM.Name + " SRM old and new tags different") + Write-Verbose ("Old Tag " + $OldTagName) + Write-Verbose ("New Tag " + $NewTagName) + + If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works + #Get-Tag -Category AppName -Name $NewTagName -Server $VIServer + If ($NewTagName -ne "None") { + New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'VR RPO' -Name $NewTagName) -Server $VIServer + Write-Verbose ($VM.Name + " tag updated " + $VIServer) + } + else { + Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer) + } + + }#> + } + Else { + + } + #} + <#catch { + Write-Error ($VM.Name + " tag errored") + Write-Error $error[-1] + }#> + } + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTagFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTagFromCmdb.ps1 new file mode 100644 index 0000000..6e201af --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMTagFromCmdb.ps1 @@ -0,0 +1,119 @@ +<# +.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 Set-ITDVMwareVMTagFromCmdb { + [CmdletBinding()] + param ( + [Parameter( + Mandatory = $true, + ValueFromPipeline = $true, + ParameterSetName = 'VMName' + )] + [string] + $VMName + ) + + begin { + #$Result = [System.Collections.ArrayList]@() + } + + process { + $HostName = $VMName.split('.')[0] + Write-Verbose -Message "Looking up Cmdb Object named $HostName" + $Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName" + + If($null -eq $Cmdb) { + Write-Warning -Message "No Cmdb Object found for $HostName" + return + } + + $VM = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } | Sort-Object Name + $OldTags = Get-TagAssignment -Entity $VM + + $obj = [PSCustomObject]@{ + VMName = $VMName; + DTAP = $null; + AppName = $null; + LicensingRestrictions = $null; + DRProtection = $null; + SRMRecoveryType = $null; + } + # DTAP + If ($Cmdb.environment.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'DTAP' }).Tag.Name + If ($Cmdb.environment.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $VMName DTAP Tag to " + $Cmdb.environment.display_value) + Set-ITDVMwareVMTag -ComputerName $VMName -Dtap $Cmdb.environment.display_value + } + Else { + + } + } + + # AppName + If ($Cmdb.u_nd_application_svc.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'AppName' }).Tag.Name + If ($Cmdb.u_nd_application_svc.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $VMName AppName Tag to " + $Cmdb.u_nd_application_svc.display_value) + Set-ITDVMwareVMTag -ComputerName $VMName -AppName $Cmdb.u_nd_application_svc.display_value + } + Else { + + } + } + + # Licensing Restrictions + If ($Cmdb.u_nd_licensing_restrictions.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'LicensingRestrictions' }).Tag.Name + If ($Cmdb.u_nd_licensing_restrictions.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $VMName Licensing Restrictions Tag to " + $Cmdb.u_nd_licensing_restrictions.display_value) + Set-ITDVMwareVMTag -ComputerName $VMName -LicensingRestrictions $Cmdb.u_nd_licensing_restrictions.display_value + } + Else { + + } + } + + # startup priority TBD + # startup priority is not in Cmdb + + # SRM Recovery Type + If ($Cmdb.u_srm_recovery_type.display_value) { + $TagAssignmentValue = ($OldTags | Where-Object { $_.Tag.Category.Name -eq 'SRM Recovery Type' }).Tag.Name + If ($Cmdb.u_srm_recovery_type.display_value -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $VMName SRM Recovery Type Tag to " + $Cmdb.u_srm_recovery_type.display_value) + Set-ITDVMwareVMTag -ComputerName $VMName -SRMRecoveryType $Cmdb.u_srm_recovery_type.display_value + } + Else { + + } + } + # + # DR Protection + If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") ) { #-replace "VMware: " -replace "RPO", "VR RPO" + $TagAssignmentValue = ($OldTags | Where-Object {$_.Tag.Category.Name -eq 'DR Protection' }).Tag.Name + If ( ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") -ne $TagAssignmentValue) { + Write-Verbose -Message ("Setting $VMName DR Protection Tag to " + ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: ") ) + Set-ITDVMwareVMTag -ComputerName $VMName -DRProtection ($Cmdb.u_nd_dr_protection.display_value -replace "VMware: " -replace "RPO", "VR RPO") + } + Else { + + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMViaSnowTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMViaSnowTask.ps1 new file mode 100644 index 0000000..37d82fb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMViaSnowTask.ps1 @@ -0,0 +1,250 @@ +<# +.SYNOPSIS + Function to process a VMware change request +.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 Set-ITDVMwareVMViaSnowTask { + [CmdletBinding()] + param ( + [string] + $SCTaskNum, + + [switch] + $Override, + + [switch] + $CloseTask + ) + + begin { + $FreePercentThreshold = 0.20 # 20% free space required before disk expansions are automated + } + + process { + # get current user, SCTask, Ritm + $assignTo = Get-ITDServiceNowUser -Username $Env:USERNAME + $SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet + $RitmNum = $Ritm.number.value + + # Get Hostname and CMDB object + [string]$SCTaskDescriptionHostname = $SCTask.description.display_value.split(' ')[-1] + $TaskCmdb = @() + + Write-Verbose -Message ("Gathering VariableSet data from $RitmNum") + $MatchFound = $false + ForEach ($Row in $Ritm.VariableSet) { + $TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop + If ($SCTaskDescriptionHostname -eq $TempCi.name.display_value) { + $Ci = $TempCi + $MatchFound = $true + } + } + + If ($MatchFound -eq $false) { + Write-Error -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -ErrorAction Stop + } + + $FQDN = $Ci.fqdn.display_value + + If ( @($Ci).count -gt 1 ) { + Write-Error -Message "More than one CMDB object found that matches the hostname in this task's description" -ErrorAction Stop + } + + # update SCTask description and assignment for humans + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{assigned_to = $assignTo.name } + + # search for VMware VM + try { + $VM = Get-VM -Name $Ci.fqdn.display_value | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + } + catch { + Write-Error "Error on VM lookup. Are you connected to vCenter?" -ErrorAction Stop + } + + switch ( @($VM).count ) { + { 0 -or $null } { + # no matches + Write-Error -Message "Zero VM matches found, ending script" -ErrorAction Stop + } + { $_ -ne 1 } { + # more than one match + Write-Error -Message "Multiple VM matches found, ending script" -ErrorAction Stop + } + { 1 } { + # exactly one match, gather request information, and populate variables + Write-Verbose -Message ("VM: " + $VM.Name) + [int]$CPU = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).Processors + [int]$MemoryGB = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).memory_gb + [int]$Disk1 = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).disk_1_os + [int]$Disk2 = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).disk_2_swap_disk + + 3..16 | ForEach-Object { + $DiskNum = $_ + Write-Verbose "Populating variable Disk$DiskNum" + ###Set-Variable -Name "Disk$DiskNum" -Value ([int](($Ritm.CustomVariable | Where-Object Name -Like "disk_$DiskNum*").Value)) + Set-Variable -Name "Disk$DiskNum" -Value ([int]( ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } )."disk_$DiskNum")) + } + + # CPU modification + If ($CPU -ne 0 -and $CPU -ne $VM.NumCpu) { + Write-Verbose -Message ($VM.Name + " attempt changing CPU from " + $VM.NumCPU + " to " + $CPU) + try { + $OldCpu = $VM.NumCpu + $VM | Set-VM -NumCpu $CPU -Confirm:$false -ErrorAction Stop + $CommentsForWorkNotes += "CPU was updated from $OldCpu to $CPU. `n" + } + catch { + + } + } + + # MemoryGB modification + If ($MemoryGB -ne 0 -and $MemoryGB -ne $VM.MemoryGB) { + Write-Verbose -Message ($VM.Name + " attempt changing MemoryGB to " + $MemoryGB) + try { + $OldMemoryGB = $VM.MemoryGB + $VM | Set-VM -MemoryGB $MemoryGB -Confirm:$false -ErrorAction Stop + $CommentsForWorkNotes += "MemoryGB was updated from $OldMemoryGB to $MemoryGB. `n" + } + catch { + + } + } + + # Disk modification loop + $VMDisks = $VM | Get-HardDisk + 1..16 | ForEach-Object { + Write-Verbose "Start Loop for Disk $_" + $HardDisk = $null + $DiskGBNewValue = $null + $DiskVarName = $null + + $DiskNum = $_ + $DiskGBNewValue = (Get-Variable -Name Disk$DiskNum).Value + + switch ($DiskNum){ + 1 { + $DiskVarName = "Disk1" + } + 2 { + $DiskVarName = "Disk2" + } + Default { + $DiskVarName = ("Disk" + $DiskNum) + } + } + + If ( (Get-Variable -Name $DiskVarName).Value -ne 0 ) { + Write-Verbose -Message ("DiskNum: $DiskNum, DiskGBNewValue: $DiskGBNewValue") + + $HardDisk = $VM | Get-HardDisk -Name "Hard disk $DiskNum" -ErrorAction SilentlyContinue + If ($HardDisk) { + $Datastore = $HardDisk | Get-Datastore + $DiskGBOldValue = $HardDisk.CapacityGB + $HardDiskIncreaseGB = $DiskGBNewValue - $DiskGBOldValue + If ($HardDiskIncreaseGB -ge 500) { + # manual intervention + } + $FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB + $FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB + + Write-Verbose -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore, 4) + " to " + [math]::round($FreePercentAfter, 4) + "") -Verbose + Write-Verbose -Message ("Override is " + $Override) + If ( ($FreePercentAfter -gt $FreePercentThreshold) -or ($Override -eq $true)) { + try { + Write-Verbose -Message ("Hard disk $DiskNum : Increasing from " + $HardDisk.CapacityGB + "GB to " + $DiskGBNewValue + "GB") -Verbose + + $VM | Get-HardDisk -Name "Hard disk $DiskNum" | Set-HardDisk -CapacityGB $DiskGBNewValue -Confirm:$false + $CommentsForWorkNotes += "Hard disk $DiskNum CapacityGB was modified from $DiskGBOldValue GB to $DiskGBNewValue GB. `n" + $DiskChanged = $true + } + catch { + Write-Error -Message "Disk $DiskNum expansion failed" -ErrorAction Stop + } + } + Else { + try { + Write-Error -Message ("Hard disk $DiskNum failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".") -ErrorAction Stop + } + catch { + Write-Error -Message ("Hard disk $DiskNum failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".") -ErrorAction Stop + } + } + } + Else { + Write-Verbose "Hard disk $DiskNum was not found. New disk will attempt to be created." -Verbose + # get licensing and storage format of existing disks + $VMTag = Get-TagAssignment -Entity $VM -Category LicensingRestrictions + If (@($VMDisks | Where-Object StorageFormat -Like "*Thick*").count -gt 0) { + $StorageFormat = 'EagerZeroedThick' + } + Else { + $StorageFormat = 'Thin' + } + + # if not SQL, validate available space and create if possible. if VM is SQL, stop + If ($VMTag.Tag.Name -notlike "*SQL*") { + # place new disk with disk 1 and validate datastore free space + $Datastore = $VM | Get-HardDisk -Name "Hard disk 1" | Get-Datastore + $DiskGBOldValue = 0 + $HardDiskIncreaseGB = $DiskGBNewValue - $DiskGBOldValue + If ($HardDiskIncreaseGB -ge 500) { + # manual intervention ? + } + $FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB + $FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB + + #create the disk, with decided storageformat and persistent persistence on hard disk 1 datastore + If ($FreePercentAfter -gt $FreePercentThreshold) { + try { + Write-Warning -Message ("Hard disk $DiskNum : Creating new disk " + $DiskGBNewValue + " GB") + #Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4)*100 + "% to " + [math]::round($FreePercentAfter,4)*100 + "%") + Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore, 4) + " to " + [math]::round($FreePercentAfter, 4) + "") + $VM | New-HardDisk -CapacityGB $DiskGBNewValue -StorageFormat $StorageFormat + $CommentsForWorkNotes += "Hard disk $DiskNum was created with $DiskGBNewValue GB. " + $DiskChanged = $true + } + catch { + + } + } + Else { + Write-Error -Message ("Hard disk $_ failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".") + $DiskChanged = $false + $DiskError = $true + } + } + Else { + # require human review + Write-Error -Message ($HostName + " has SQL licensing, create the new disk manually due to SQL Server best practices. Once complete, rerun to validate size and close task.") -ErrorAction Stop + } + } + } + } + + # update sctask and ritm, reassign if disk changed + $CommentsToAdd = "VMware VM " + $VM.Name + " was modified: `n" + $CommentsForWorkNotes + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{comments = $CommentsToAdd } + Update-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -Values @{comments = $CommentsToAdd } + + If ($CloseTask) { + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{close_notes = $CommentsToAdd; state = "Closed Complete" } + } + } + } + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMMetadataToSharePoint.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMMetadataToSharePoint.ps1 new file mode 100644 index 0000000..5f97306 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMMetadataToSharePoint.ps1 @@ -0,0 +1,239 @@ +function Sync-ITDVMwareVMMetadataToSharePoint { + [CmdletBinding()] + param ( + [string[]] + $VMName, + + [switch] + $SRMImplemented, + + [switch] + $WhatIf + ) + + begin { + + } + + process { + # validate vcenter connection + # search for sharepoint record + # if multiple, error + # get VM (non-placeholder) information + # name, cpu, memoryGB, disks, cluster, datacenter + # compare, discover fields that are mismatched + # if SRMImplement -eq $true, set SP record to match that + # set sharepoint record to values pulled from vcenter + + If ($global:DefaultVIServers) { + + } + Else { + Write-Error -Message "Not connected to vCenter" -ErrorAction Stop + } + + Write-Verbose -Message "Get SharePoint Cluster List" + $SharePointClusterList = Get-ITDSharePointVMClusterList + Write-Verbose -Message "Get SharePoint Guest List" + $SharePointVMList = Get-ITDSharePointVMGuestList + + ForEach ($ComputerName in $VMName) { + Write-Verbose -Message "Start $ComputerName" + $RecordToUpdate = $SharePointVMList | Where-Object Title -EQ $ComputerName + $VM = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } + switch (@($VM).count) { + { $_ -le 0 } { + Write-Error -Message "No virtual machine found with name $ComputerName" -ErrorAction Stop + } + { $_ -gt 1 } { + Write-Error -Message "More than one virtual machine found with name $ComputerName" -ErrorAction Stop + } + { 1 } { + switch (@($RecordToUpdate).count) { + { $_ -le 0 } { + Write-Error "SharePoint record with Title $ComputerName not found. Create the new record first." -ErrorAction Stop + } + { $_ -gt 1 } { + Write-Error "More than one SharePoint record found with Title equal to $ComputerName" -ErrorAction Stop + } + { 1 } { + # get virtual hard disks and load variables + $VMDisks = $VM | Get-HardDisk + $VMDisk1 = ($VMDisks | Where-Object Name -EQ "Hard Disk 1").CapacityGB + $VMDisk2 = ($VMDisks | Where-Object Name -EQ "Hard Disk 2").CapacityGB + $VMDisk3 = ($VMDisks | Where-Object Name -EQ "Hard Disk 3").CapacityGB + $VMDisk4 = ($VMDisks | Where-Object Name -EQ "Hard Disk 4").CapacityGB + $VMDisk5 = ($VMDisks | Where-Object Name -EQ "Hard Disk 5").CapacityGB + $VMDisk6 = ($VMDisks | Where-Object Name -EQ "Hard Disk 6").CapacityGB + $VMDisk7 = ($VMDisks | Where-Object Name -EQ "Hard Disk 7").CapacityGB + $VMDisk8 = ($VMDisks | Where-Object Name -EQ "Hard Disk 8").CapacityGB + $VMDisk9 = ($VMDisks | Where-Object Name -EQ "Hard Disk 9").CapacityGB + $VMDisk10 = ($VMDisks | Where-Object Name -EQ "Hard Disk 10").CapacityGB + $VMDisk11 = ($VMDisks | Where-Object Name -EQ "Hard Disk 11").CapacityGB + $VMDisk12 = ($VMDisks | Where-Object Name -EQ "Hard Disk 12").CapacityGB + $VMDisk13 = ($VMDisks | Where-Object Name -EQ "Hard Disk 13").CapacityGB + $VMDisk14 = ($VMDisks | Where-Object Name -EQ "Hard Disk 14").CapacityGB + $VMDisk15 = ($VMDisks | Where-Object Name -EQ "Hard Disk 15").CapacityGB + $VMDisk16 = ($VMDisks | Where-Object { $_.Name.split(' ')[2] -notmatch '\b([1-9]|1[0-5])\b' } | Measure-Object -Sum CapacityGB).Sum + + If ($null -eq $VMDisk1 ) { $VMDisk1 = 0 } + If ($null -eq $VMDisk2 ) { $VMDisk2 = 0 } + If ($null -eq $VMDisk3 ) { $VMDisk3 = 0 } + If ($null -eq $VMDisk4 ) { $VMDisk4 = 0 } + If ($null -eq $VMDisk5 ) { $VMDisk5 = 0 } + If ($null -eq $VMDisk6 ) { $VMDisk6 = 0 } + If ($null -eq $VMDisk7 ) { $VMDisk7 = 0 } + If ($null -eq $VMDisk8 ) { $VMDisk8 = 0 } + If ($null -eq $VMDisk9 ) { $VMDisk9 = 0 } + If ($null -eq $VMDisk10) { $VMDisk10 = 0 } + If ($null -eq $VMDisk11) { $VMDisk11 = 0 } + If ($null -eq $VMDisk12) { $VMDisk12 = 0 } + If ($null -eq $VMDisk13) { $VMDisk13 = 0 } + If ($null -eq $VMDisk14) { $VMDisk14 = 0 } + If ($null -eq $VMDisk15) { $VMDisk15 = 0 } + If ($null -eq $VMDisk16) { $VMDisk16 = 0 } + + # Get VMware Cluster + # what vcenter says, and what it should be + $vCenterCluster = $VM | Get-Cluster + $vCenterSharePointClusterItem = $SharePointClusterList | Where-Object Name -EQ $vCenterCluster.Name + # what sharepoint currently is + $SharePointClusterFieldId = $RecordToUpdate.ClusterId + $SharePointClusterFieldName = $SharePointClusterList | Where-Object Id -EQ $SharePointClusterFieldId + + # Get VMware Datacenter + $Datacenter = $VM | Get-Datacenter + + switch ($Datacenter.Name) { + 'DCN Datacenter' { $DatacenterSharePointName = "DCN" } + 'Fargo Datacenter' { $DatacenterSharePointName = "Fargo" } + 'Grand Forks Vantis' { $DatacenterSharePointName = "Grand Forks" } + 'Primary Datacenter' { $DatacenterSharePointName = "Bismarck" } + 'Secondary Datacenter' { $DatacenterSharePointName = "Mandan" } + 'VDI Datacenter' { $DatacenterSharePointName = "VDI" } + } + + # one sharepoint record and one virtual machine, compare and set params + $SetITDVMwareSharePointVMRecordParams = @{ + Title = $ComputerName; + } + + [string]$SpecialInstructions = ([string](Get-Date) + " - synchronization from vCenter, the following was changed: ") + + If ($VM.NumCPU -ne $RecordToUpdate.Processors) { + $SetITDVMwareSharePointVMRecordParams += @{CPU = $VM.NumCpu } + $SpecialInstructions += ("CPU adjusted from " + $RecordToUpdate.Processors + " to " + $VM.NumCpu + ". ") + } + If ($VM.MemoryGB -ne $RecordToUpdate.RAM) { + $SetITDVMwareSharePointVMRecordParams += @{MemoryGB = $VM.MemoryGB } + $SpecialInstructions += ("MemoryGB adjusted from " + $RecordToUpdate.RAM + " to " + $VM.MemoryGB + ". ") + } + + If ($VMDisk1 -ne $RecordToUpdate.Disk_x0020_C_x003a_) { + $SetITDVMwareSharePointVMRecordParams += @{Disk1OS = $VMDisk1 } + $SpecialInstructions += ("Disk1GB adjusted from " + $RecordToUpdate.Disk_x0020_C_x003a_ + " to " + $VMDisk1 + ". ") + } + If ($VMDisk2 -ne $RecordToUpdate.Disk2_x002d_SwapDisk) { + $SetITDVMwareSharePointVMRecordParams += @{Disk2Swap = $VMDisk2 } + $SpecialInstructions += ("Disk2GB adjusted from " + $RecordToUpdate.Disk2_x002d_SwapDisk + " to " + $VMDisk2 + ". ") + } + If ($VMDisk3 -ne $RecordToUpdate.Disk_x0020_D_x003a_) { + $SetITDVMwareSharePointVMRecordParams += @{Disk3 = $VMDisk3 } + $SpecialInstructions += ("Disk3GB adjusted from " + $RecordToUpdate.Disk_x0020_D_x003a_ + " to " + $VMDisk3 + ". ") + } + If ($VMDisk4 -ne $RecordToUpdate.Disk_x0020__x002d__x0020_Other) { + $SetITDVMwareSharePointVMRecordParams += @{Disk4 = $VMDisk4 } + $SpecialInstructions += ("Disk4GB adjusted from " + $RecordToUpdate.Disk_x0020__x002d__x0020_Other + " to " + $VMDisk4 + ". ") + } + If ($VMDisk5 -ne $RecordToUpdate.Disk5) { + $SetITDVMwareSharePointVMRecordParams += @{Disk5 = $VMDisk5 } + $SpecialInstructions += ("Disk5GB adjusted from " + $RecordToUpdate.Disk5 + " to " + $VMDisk5 + ". ") + } + If ($VMDisk6 -ne $RecordToUpdate.Disk6) { + $SetITDVMwareSharePointVMRecordParams += @{Disk6 = $VMDisk6 } + $SpecialInstructions += ("Disk6GB adjusted from " + $RecordToUpdate.Disk6 + " to " + $VMDisk6 + ". ") + } + If ($VMDisk7 -ne $RecordToUpdate.Disk7) { + $SetITDVMwareSharePointVMRecordParams += @{Disk7 = $VMDisk7 } + $SpecialInstructions += ("Disk7GB adjusted from " + $RecordToUpdate.Disk7 + " to " + $VMDisk7 + ". ") + } + If ($VMDisk8 -ne $RecordToUpdate.Disk8) { + $SetITDVMwareSharePointVMRecordParams += @{Disk8 = $VMDisk8 } + $SpecialInstructions += ("Disk8GB adjusted from " + $RecordToUpdate.Disk8 + " to " + $VMDisk8 + ". ") + } + If ($VMDisk9 -ne $RecordToUpdate.Disk9) { + $SetITDVMwareSharePointVMRecordParams += @{Disk9 = $VMDisk9 } + $SpecialInstructions += ("Disk9GB adjusted from " + $RecordToUpdate.Disk9 + " to " + $VMDisk9 + ". ") + } + If ($VMDisk10 -ne $RecordToUpdate.Disk10) { + $SetITDVMwareSharePointVMRecordParams += @{Disk10 = $VMDisk10 } + $SpecialInstructions += ("Disk10GB adjusted from " + $RecordToUpdate.Disk10 + " to " + $VMDisk10 + ". ") + } + If ($VMDisk11 -ne $RecordToUpdate.Disk11) { + $SetITDVMwareSharePointVMRecordParams += @{Disk11 = $VMDisk11 } + $SpecialInstructions += ("Disk11GB adjusted from " + $RecordToUpdate.Disk11 + " to " + $VMDisk11 + ". ") + } + If ($VMDisk12 -ne $RecordToUpdate.Disk12) { + $SetITDVMwareSharePointVMRecordParams += @{Disk12 = $VMDisk12 } + $SpecialInstructions += ("Disk12GB adjusted from " + $RecordToUpdate.Disk12 + " to " + $VMDisk12 + ". ") + } + If ($VMDisk13 -ne $RecordToUpdate.Disk13) { + $SetITDVMwareSharePointVMRecordParams += @{Disk13 = $VMDisk13 } + $SpecialInstructions += ("Disk13GB adjusted from " + $RecordToUpdate.Disk13 + " to " + $VMDisk13 + ". ") + } + If ($VMDisk14 -ne $RecordToUpdate.Disk14) { + $SetITDVMwareSharePointVMRecordParams += @{Disk14 = $VMDisk14 } + $SpecialInstructions += ("Disk14GB adjusted from " + $RecordToUpdate.Disk14 + " to " + $VMDisk14 + ". ") + } + If ($VMDisk15 -ne $RecordToUpdate.Disk15) { + $SetITDVMwareSharePointVMRecordParams += @{Disk15 = $VMDisk15 } + $SpecialInstructions += ("Disk15GB adjusted from " + $RecordToUpdate.Disk15 + " to " + $VMDisk15 + ". ") + } + If ($VMDisk16 -ne $RecordToUpdate.Disk16) { + $SetITDVMwareSharePointVMRecordParams += @{Disk16 = $VMDisk16 } + $SpecialInstructions += ("Disk16GB adjusted from " + $RecordToUpdate.Disk16 + " to " + $VMDisk16 + ". ") + } + + If ($vCenterCluster.Name -ne $SharePointClusterFieldName.Name) { + $SetITDVMwareSharePointVMRecordParams += @{ClusterId = $vCenterSharePointClusterItem.Id } + $SpecialInstructions += ("ClusterId adjusted from " + $RecordToUpdate.ClusterId + " to " + $vCenterSharePointClusterItem.Id + ". ") + $SpecialInstructions += ("Cluster adjusted to " + $vCenterSharePointClusterItem.Name + ". ") + } + If ($DatacenterSharePointName -ne $RecordToUpdate.Datacenter) { + $SetITDVMwareSharePointVMRecordParams += @{'Datacenter' = $DatacenterSharePointName } + $SpecialInstructions += ("Datacenter adjusted from " + $RecordToUpdate.Datacenter + " to " + $DatacenterSharePointName + ". ") + } + + If($PSBoundParameters.ContainsKey('SRMImplemented')){ + $SetITDVMwareSharePointVMRecordParams += @{SRM_Status = 'Implemented'} + $SpecialInstructions += ("SRM_Status set to Implemented. SRM_RecoveryVMtype set to Reserved. SRM_ConfiguredDate set to " + (Get-Date)) + } + + $SetITDVMwareSharePointVMRecordParams += @{SpecialInstructions = $SpecialInstructions } + + If ($WhatIf) { + Write-Warning -Message ("The following fields in SharePoint record #" + $RecordToUpdate.ID + " for Title " + $RecordToUpdate.Title + " would be changed:") + $SetITDVMwareSharePointVMRecordParams + } + Else { + $SetITDVMwareSharePointVMRecordParams + Set-ITDVMwareSharePointVMRecord @SetITDVMwareSharePointVMRecordParams #-Verbose + } + } + } + } + } + } + } + + end { + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Change'; + Units = 3; + Platform = 'ServiceNow-Overhead-SharePointDualEntry'; + } + + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) | Out-Null + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMTagsFromCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMTagsFromCmdb.ps1 new file mode 100644 index 0000000..b09193c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Sync-ITDVMwareVMTagsFromCmdb.ps1 @@ -0,0 +1,154 @@ +<# +.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 Sync-ITDVMwareVMTagsFromCmdb { + [CmdletBinding()] + param ( + + ) + + begin { + + } + + process { + $GetITDServiceNowRecordParams = @{ + #Filter = "model_idLIKEVMware" + Table = 'cmdb_ci_server'; + IncludeTotalCount = $true; + Fields = @( + 'name', + 'fqdn', + 'environment', + 'u_nd_type', + 'model_id', + 'os', + 'os_version', + 'u_nd_application_svc', + 'u_nd_licensing_restrictions', + 'u_nd_dr_protection', + 'u_srm_recovery_type' + ) + } + + Write-Verbose -Message 'Retrieve all CMDB CIs' + $AllCmdb = Get-ITDServiceNowRecord @GetITDServiceNowRecordParams + $AllCmdbValues = $AllCmdb | Select-Object @{n = 'Name'; e = { $_.Name.display_value } }, + @{n = 'fqdn'; e = { $_.fqdn.display_value } }, + @{n = 'DTAP'; e = { $_.environment.display_value } }, + @{n = 'environment'; e = { $_.u_nd_type.display_value } }, + @{n = 'type'; e = { $_.u_nd_type.display_value } }, + @{n = 'model_id'; e = { $_.model_id.display_value } }, + @{n = 'os'; e = { $_.os.display_value } }, + @{n = 'os_version'; e = { $_.os_version.display_value } }, + @{n = 'u_nd_application_svc'; e = { $_.u_nd_application_svc.display_value } }, + @{n = 'u_nd_dr_protection'; e = { $_.u_nd_dr_protection.display_value } }, + @{n = 'u_nd_licensing_restrictions'; e = { $_.u_nd_licensing_restrictions.display_value } }, + @{n = 'u_srm_recovery_type'; e = { $_.u_srm_recovery_type.display_value } } + + # DTAP from all unique options from the cmdb_ci_server table field name "Environment" + Write-Verbose -Message "Start Environment Tag sync" + $CmdbValues = ($AllCmdbValues | Select-Object -Unique DTAP | Select-Object -ExpandProperty DTAP) + $TagValues = (Get-Tag -Category DTAP -Server itdvmvc1.nd.gov).Name + $Compare = Compare-Object -ReferenceObject $CmdbValues -DifferenceObject $TagValues + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '<=')) { + Write-Verbose -Message ("Create DTAP tag for " + $c.InputObject) + New-Tag -Category DTAP_SNow -Name $c.InputObject -Server 'itdvmvc1.nd.gov' + } + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '=>')) { + Write-Verbose -Message ("Remove DTAP tag for " + $c.InputObject) + Get-Tag -Category DTAP_SNow -Name $c.InputObject -Server 'itdvmvc1.nd.gov' | Remove-Tag -Confirm:$false + } + $TagValues = $null + $Compare = $null + Write-Verbose -Message "End Environment Tag sync" + + # AppName, get list from ServiceNow table cmdb_ci_service + Write-Verbose -Message "Start AppName Tag sync" + $AllAppNames = (Get-ITDServiceNowRecord -Table 'cmdb_ci_service' -Filter "operational_status=1" -IncludeTotalCount -Fields name).name.display_value | Where-Object { $_ -like "*-*" } + $TagValues = (Get-Tag -Category AppName -Server itdvmvc1.nd.gov).Name + $Compare = Compare-Object -ReferenceObject $AllAppNames -DifferenceObject $TagValues + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '<=')) { + Write-Verbose -Message ("Create AppName tag for " + $c.InputObject) + New-Tag -Category AppName -Name $c.InputObject -Server 'itdvmvc1.nd.gov' + } + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '=>')) { + Write-Verbose -Message ("Remove AppName tag for " + $c.InputObject) + Get-Tag -Category AppName -Name $c.InputObject -Server 'itdvmvc1.nd.gov' | Remove-Tag -Confirm:$false + } + $TagValues = $null + $Compare = $null + Write-Verbose -Message "End AppName Tag sync" + + # Licensing Restrictions + Write-Verbose -Message "Start Licensing Restrictions Tag sync" + $AllLicensingRestrictions = ($AllCmdbValues | Select-Object -Unique u_nd_licensing_restrictions | Select-Object -ExpandProperty u_nd_licensing_restrictions) + $TagValues = (Get-Tag -Category LicensingRestrictions -Server itdvmvc1.nd.gov).Name + $Compare = Compare-Object -ReferenceObject $AllLicensingRestrictions -DifferenceObject $TagValues + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '<=')) { + Write-Verbose -Message ("Create AppName tag for " + $c.InputObject) + New-Tag -Category LicensingRestrictions -Name $c.InputObject -Server 'itdvmvc1.nd.gov' + } + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '=>')) { + Write-Verbose -Message ("Remove AppName tag for " + $c.InputObject) + Get-Tag -Category LicensingRestrictions -Name $c.InputObject -Server 'itdvmvc1.nd.gov' | Remove-Tag -Confirm:$false + } + + $TagValues = $null + $Compare = $null + + # Startup Priority + # Startup Priority is not in CMDB + + # DR_Protection + Write-Verbose -Message "Start DR Protection Tag sync" + $AllDRProtection = ($AllCmdbValues | Select-Object -Unique u_nd_dr_protection | Select-Object -ExpandProperty u_nd_dr_protection) -replace "VMware: " -replace "RPO", "VR RPO" | Sort-Object + $TagValues = (Get-Tag -Category "DR Protection" -Server itdvmvc1.nd.gov).Name + $Compare = Compare-Object -ReferenceObject $AllDRProtection -DifferenceObject $TagValues + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '<=')) { + Write-Verbose -Message ("Create DR Protection tag for " + $c.InputObject) + New-Tag -Category "DR Protection" -Name $c.InputObject -Server 'itdvmvc1.nd.gov' + } + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '=>')) { + Write-Verbose -Message ("Create Protection tag for " + $c.InputObject) + Get-Tag -Category "DR Protection" -Name $c.InputObject -Server 'itdvmvc1.nd.gov' | Remove-Tag -Confirm:$false + } + + $TagValues = $null + $Compare = $null + Write-Verbose -Message "End DR Protection Tag sync" + + # SRM Recovery Type + Write-Verbose -Message "Start SRM Recovery Type Tag sync" + $AllSRMRecoveryType = ($AllCmdbValues | Select-Object -Unique u_srm_recovery_type | Select-Object -ExpandProperty u_srm_recovery_type) + $TagValues = (Get-Tag -Category "SRM Recovery Type" -Server itdvmvc1.nd.gov).Name + $Compare = Compare-Object -ReferenceObject $AllSRMRecoveryType -DifferenceObject $TagValues | Where-Object InputObject -NE "Placeholder" + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '<=')) { + Write-Verbose -Message ("Create SRM Recovery Type tag for " + $c.InputObject) + New-Tag -Category LicensingRestrictions -Name $c.InputObject -Server 'itdvmvc1.nd.gov' + } + ForEach ($c in ($Compare | Where-Object SideIndicator -EQ '=>')) { + Write-Verbose -Message ("Remove SRM Recovery Type tag for " + $c.InputObject) + Get-Tag -Category LicensingRestrictions -Name $c.InputObject -Server 'itdvmvc1.nd.gov' | Remove-Tag -Confirm:$false + } + + $TagValues = $null + $Compare = $null + Write-Verbose -Message "End SRM Recovery Type Tag sync" + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTask.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTask.ps1 new file mode 100644 index 0000000..ecb8f5c --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTask.ps1 @@ -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 Update-ITDSNowVMTask { + [CmdletBinding()] + param ( + [string] + $SCTaskNum, + + [string] + $CommentsToAdd, + + [switch] + $CloseTask + ) + + begin { + + } + + process { + # get current user, SCTask, Ritm + $assignTo = Get-ServiceNowRecord -Table 'User' -Filter @('email', '-eq', ($env:username + "@nd.gov")) + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + + $Hostname = ($Ritm.CustomVariable | Where-Object Name -EQ 'server_name').Value + + # update SCTask description and assignment for humans + Write-Warning "$SCTaskNum assigned to $env:username" + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = "VMware VM modification for $HostName"; assigned_to = $assignTo.name } + + If ($CommentsToAdd) { + Update-ServiceNowRecord -ID $SCTask.number -Values @{comments = $CommentsToAdd } # enter comments into SCTASK + Update-ServiceNowRecord -ID $RitmNum -Values @{comments = $CommentsToAdd } # enter comments into RITM + } + If ($CloseTask) { + Update-ServiceNowRecord -ID $SCTask.number -Values @{close_notes = $CommentsToAdd; state = "Closed Complete" } + } + } + + end { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTaskDescription.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTaskDescription.ps1 new file mode 100644 index 0000000..6a2789f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Update-ITDSNowVMTaskDescription.ps1 @@ -0,0 +1,169 @@ +<# +.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-ITDSNowVMTaskDescription { + [CmdletBinding()] + param ( + + ) + + begin { + + } + + process { + <# Server Builds + Write-Verbose -Message "Start Server Builds" + $Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-eq', 'Automated Server Build Task for Windows Virtual Machine'), '-and', @('state', '-eq', '2') + $OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number + + ForEach ($OpenTask in $OpenTasks) { + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable -WarningAction SilentlyContinue + + $ComputerName = ($Ritm.CustomVariable | Where-Object Name -EQ host_name).Value + $OperatingSystem = ($Ritm.CustomVariable | Where-Object Name -EQ operating_system).Value + switch (($Ritm.CustomVariable | Where-Object Name -EQ target_platform).Value) { + 'azure' { $target_platform = "Azure" } + 'vmware' { $target_platform = "VMware" } + } + + # update short description + $shortdescription = "$target_platform $OperatingSystem VM Build for $ComputerName" + If ( ($RITM.CustomVariable | Where-Object Name -EQ dr_protection).Value -ne 'No DR') { + $shortdescription += ", with SRM protection" + } + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $shortdescription; } + } + Write-Verbose -Message "End Server Builds" +#> + <# VM Modifications + Write-Verbose -Message "Start VM Modifications" + $Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-eq', 'Upgrade/Code Deployment'), '-and', @('state', '-eq', '1') + $OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number + + ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message "Start $OpenTask.number" + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + + $ComputerName = ($Ritm.CustomVariable | Where-Object Name -EQ server_name).Value.tolower() + + # update short description + $shortdescription = "VM Modification for $ComputerName" + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $shortdescription; } + Write-Verbose -Message "End $OpenTask.number" + } + Write-Verbose -Message "End VM Modifications" +#> + # VM removal / retire + Write-Verbose -Message "Start Remove Server description updates" + #$Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-like', 'Retire Server'), '-and', @('state', '-eq', '1') + $Filter = "active=true^short_descriptionSTARTSWITHRemove Server: " + #$OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number + $OpenTasks = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Filter $Filter -IncludeTotalCount | Sort-Object Number + $AllRitms = [System.Collections.ArrayList]@() + + ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message ("Start " + $OpenTask.number) + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number.value + $SCTask = $OpenTask + If ($AllRitms | Where-Object sys_id -EQ $SCTask.request_item.value) { + $Ritm = $AllRitms | Where-Object sys_id -EQ $SCTask.request_item.display_value + } + Else { + $Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $SCTask.request_item.display_value -IncludeVariableSet + $null = $AllRitms.Add($Ritm) + } + + $short_description_hostname = $SCTask.short_description.display_value.split(' ')[2] + $Ci = Get-ITDServiceNowRecord -Table cmdb_ci -Filter ("name=" + $short_description_hostname) + + $HostName = $Ci.Name.display_value + $FQDN = $Ci.FQDN.display_value + + # determine if vmware, azure, or physical + switch ($Ci.model_id.display_value) { + { $_ -like "*VMware*" } { $hardware_platform = "VMware"; $hardware_type = 'Virtual Machine' } + { $_ -like "*Microsoft Virtual Machine*" } { $hardware_platform = "Azure"; $hardware_type = 'Virtual Machine' } + { $_ -like "*HP*" } { $hardware_platform = 'HPE'; $hardware_type = 'Physical' } + default { $hardware_platform = 'Unknown'; $hardware_type = 'Other' } + } + + # determine if windows, rhel, or other + switch ($Ci.sys_class_name.display_value) { + 'Linux Server' { $OS = 'Linux' } + 'Windows Server' { $OS = 'Windows' } + 'Default' { $OS = 'Other' } + } + + $short_description_new = "$hardware_platform $OS Removal for " + If ($FQDN) { + $short_description_new += $FQDN + } + Else { + $short_description_new += $ComputerName + } + #Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $shortdescription; } + Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{short_description = $short_description_new} + Write-Verbose -Message ("End " + $OpenTask.number.display_value) + } + Write-Verbose -Message "End VM removal/retire" + + <# Other Server Requests + Write-Verbose -Message "Start Other Server" + $Filter = @('assignment_group', '-like', 'NDIT-Server Build Automation'), '-and', @('short_description', '-eq', 'Other Server Request'), '-and', @('state', '-eq', '1') + $OpenTasks = Get-ServiceNowRecord -Table 'Catalog Task' -Filter $Filter | Sort-Object Number + + ForEach ($OpenTask in $OpenTasks) { + Write-Verbose -Message "Start $OpenTask.number" + # get SCTask, Ritm + $SCTaskNum = $OpenTask.number + $SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum + $RitmNum = $SCTask.request_item.display_value + $Ritm = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable + + $ComputerName = ($Ritm.CustomVariable | Where-Object Name -EQ server_name).Value + $OperatingSystem = ($Ritm.CustomVariable | Where-Object Name -EQ operating_system).Value + + # update short description + $shortdescription = "Other Server Request for $ComputerName" + Update-ServiceNowRecord -ID $SCTask.number -Values @{short_description = $shortdescription; } + Write-Verbose -Message "End $OpenTask.number" + } + Write-Verbose -Message "End Other Server" + #> + } + + end { + <# + $postParams = [PSCustomObject]@{ + AutomationName = "Infra-VMware"; + Action = 'Change'; + Units = 3; + Platform = 'ServiceNow-Overhead'; + } + + Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) +#> + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/README.md b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/SQL/snapshottable.sql b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/SQL/snapshottable.sql new file mode 100644 index 0000000..c54cecf --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/SQL/snapshottable.sql @@ -0,0 +1,12 @@ +CREATE TABLE Infra_VMware_VirtualMachine_VMSnapshots_NPD ( + ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, + VMName varchar(255) NOT NULL, + DateTime DateTime NOT NULL, + RequestedBy varchar(255) NOT NULL, + DurationHours int NOT NULL, + Status varchar(255) NOT NULL, + NotifyEmail varchar(255), + TakenDateTime DateTime, + ExpireDateTime DateTime, + DeleteDateTime DateTime +) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Scripts_PSU/Update-ITDSNowVMTaskDescription_script.ps1 b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Scripts_PSU/Update-ITDSNowVMTaskDescription_script.ps1 new file mode 100644 index 0000000..4f8e0eb --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Scripts_PSU/Update-ITDSNowVMTaskDescription_script.ps1 @@ -0,0 +1,2 @@ +New-ServiceNowSession -Url 'northdakota.service-now.com' -Credential $Secret:SNowVMCred -WarningAction SilentlyContinue +Update-ITDSNowVMTaskDescription -Verbose \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.POC/Build/azure-pipelines.yml new file mode 100644 index 0000000..311821e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.POC' + +variables: + major: 0 + minor: 3 + 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.POC.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.POC.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.POC/Build/build.ps1 new file mode 100644 index 0000000..b0c5e2e --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.POC' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.POC).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Build/deploy.ps1 b/_NDGOV_WindowsTeam/ITD.POC/Build/deploy.ps1 new file mode 100644 index 0000000..e054cb7 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Build/deploy.ps1 @@ -0,0 +1,10 @@ +$moduleName = 'ITD.POC' + +Register-PSRepository -Name ITD_PwshGalleryPOC ` + -SourceLocation https://itdscmt1.nd.gov/ITD_PwshGallery/nuget/ ` + -PublishLocation https://itdscmt1.nd.gov/ITD_PwshGallery/nuget/ ` + -InstallationPolicy Trusted + +#$modulePath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psm1" + +Publish-Module -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -Repository ITD_PwshGalleryPOC -NuGetApiKey 'zm' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.nuspec b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.nuspec new file mode 100644 index 0000000..a824e09 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.nuspec @@ -0,0 +1,12 @@ + + + + ITD.POC + $VERSIONHERE$ + Zack Meier + It's a POC, don't expect much from this + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psd1 b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psd1 new file mode 100644 index 0000000..9050e60 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psd1 @@ -0,0 +1,133 @@ +# +# Module manifest for module 'ITD.POC' +# +# Generated by: zmeier +# +# Generated on: 5/19/2022 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.POC.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = 'd1cf6cf9-b109-4a16-82ca-88f19f8a2952' + + # Author of this module + Author = 'zmeier' + + # Company or vendor of this module + CompanyName = 'Unknown' + + # Copyright statement for this module + Copyright = '(c) zmeier. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'POC Pwsh Module' + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psm1 b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psm1 new file mode 100644 index 0000000..0848867 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/ITD.POC.psm1 @@ -0,0 +1,27 @@ +#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 +# Export Public functions ($Public.BaseName) for WIP modules +# Set variables visible to the module and its functions only + +Export-ModuleMember -Function $Public.Basename + +$POCVars = @{ + FQDN = 'thisisafqdn.nd.gov' +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Private/Get-PrivateStuff.ps1 b/_NDGOV_WindowsTeam/ITD.POC/Private/Get-PrivateStuff.ps1 new file mode 100644 index 0000000..5737d7f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Private/Get-PrivateStuff.ps1 @@ -0,0 +1,40 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Get-PrivateStuff +{ + [CmdletBinding()] + Param + ( + ) + + Begin + { + } + Process + { + Write-Warning -Message ("This is private stuff") + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicAndPrivateStuff.ps1 b/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicAndPrivateStuff.ps1 new file mode 100644 index 0000000..e2cd0ea --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicAndPrivateStuff.ps1 @@ -0,0 +1,41 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Get-PublicandPrivateStuff +{ + [CmdletBinding()] + Param + ( + ) + + Begin + { + } + Process + { + Get-PublicStuff + Get-PrivateStuff + } + End + { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicStuff.ps1 b/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicStuff.ps1 new file mode 100644 index 0000000..273e9b8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/Public/Get-PublicStuff.ps1 @@ -0,0 +1,37 @@ +<# +.Synopsis + Short description +.DESCRIPTION + Long description +.EXAMPLE + Example of how to use this cmdlet +.EXAMPLE + Another example of how to use this cmdlet +.INPUTS + Inputs to this cmdlet (if any) +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + The component this cmdlet belongs to +.ROLE + The role this cmdlet belongs to +.FUNCTIONALITY + The functionality that best describes this cmdlet +#> +function Get-PublicStuff { + [CmdletBinding()] + Param + ( + ) + + Begin { + } + Process { + Write-Warning -Message ("This is public stuff") + Write-Warning -Message ("POCVars FQDN value is " + $POCVars.FQDN) + } + End { + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.POC/README.md b/_NDGOV_WindowsTeam/ITD.POC/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.POC/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.SQL.General/Build/azure-pipelines.yml new file mode 100644 index 0000000..9dc0d56 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/Build/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - main + +name: 'ITD.SQL.General' + +variables: + major: 0 + minor: 1 + 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.SQL.General.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.SQL.General.$(major).$(minor).$(Build.BuildID).nupkg' + nuGetFeedType: external + publishFeedCredentials: 'ITD_PwshGallery' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.SQL.General/Build/build.ps1 new file mode 100644 index 0000000..2c67562 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/Build/build.ps1 @@ -0,0 +1,17 @@ +$buildVersion = $env:BUILDVER +$moduleName = 'ITD.SQL.General' + +$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 '', $buildVersion + +## Update functions to export in manifest +Import-Module $modulePath +$funcStrings = (Get-Module ITD.SQL.General).ExportedCommands.Values.Name +$funcStrings = "'$($funcStrings -join "','")'" +$manifestContent = $manifestContent -replace "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.nuspec b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.nuspec new file mode 100644 index 0000000..46ae008 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.nuspec @@ -0,0 +1,12 @@ + + + + ITD.SQL.General + $VERSIONHERE$ + Zack Meier + Functions for working with SQL databases and tables (non-administrative tasks) + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psd1 b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psd1 new file mode 100644 index 0000000..08e7bca --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'ITD.SQL.General' +# +# Generated by: zmeier +# +# Generated on: 12/07/2023 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'ITD.SQL.General.psm1' + + # Version number of this module. + ModuleVersion = '' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = 'c7984785-8fc6-4d39-be28-d1a0e2451b37' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psm1 b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psm1 new file mode 100644 index 0000000..598fa57 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/ITD.SQL.General.psm1 @@ -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 \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/Public/Invoke-ITDSqlCmdJob.ps1 b/_NDGOV_WindowsTeam/ITD.SQL.General/Public/Invoke-ITDSqlCmdJob.ps1 new file mode 100644 index 0000000..ac022a4 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/Public/Invoke-ITDSqlCmdJob.ps1 @@ -0,0 +1,65 @@ +<# +.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 Invoke-ITDSqlCmdJob { + [CmdletBinding()] + param( + [string] + $ServerInstance, + + [string] + $Database, + + [string] + $Query, + + [PSCredential] + $Credential + ) + + begin { + + } + + process { + + $ScriptBlock = { + param($ServerInstance, $Database, $Query) + $ErrorActionPreference = 'Stop'; + + return [PSCustomObject]@{ + Result = (Invoke-Sqlcmd -ServerInstance $ServerInstance -Query $Query -Database $Database) + } + } + + $Job = Start-Job -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $ServerInstance, $Database, $SqlQuery + (Wait-Job -Job $Job | Receive-Job -Keep).Result + #$Result = $Job | Receive-Job -Keep + } + + end { + #Write-Output $Result + } +} + + + +<#$ScriptBlock = { + param($SqlServer, $Database, $Query) + $ErrorActionPreference = 'Stop'; + + return @{ Result = Invoke-Sqlcmd -ServerInstance $SqlServer -Query $Query -Database $Database } +} + +$Job = Start-Job -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $SqlServer,$Database,$SqlQuery#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.SQL.General/README.md b/_NDGOV_WindowsTeam/ITD.SQL.General/README.md new file mode 100644 index 0000000..e37e4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.SQL.General/README.md @@ -0,0 +1,20 @@ +# Introduction +TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. + +# Getting Started +TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: +1. Installation process +2. Software dependencies +3. Latest releases +4. API references + +# Build and Test +TODO: Describe and show how to build your code and run the tests. + +# Contribute +TODO: Explain how other users and developers can contribute to make your code better. + +If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: +- [ASP.NET Core](https://github.com/aspnet/Home) +- [Visual Studio Code](https://github.com/Microsoft/vscode) +- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/azure-pipelines.yml b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/azure-pipelines.yml new file mode 100644 index 0000000..36d698b --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/azure-pipelines.yml @@ -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' \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/build.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/build.ps1 new file mode 100644 index 0000000..ddeea2d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Build/build.ps1 @@ -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 '', $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 "", $funcStrings + +$manifestContent | Set-Content -Path $manifestPath \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.nuspec b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.nuspec new file mode 100644 index 0000000..f619f60 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.nuspec @@ -0,0 +1,12 @@ + + + + ITD.Shared-ServiceNow + $VERSIONHERE$ + Zack Meier + Functions for ServiceNow API interaction + + + + + \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psd1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psd1 new file mode 100644 index 0000000..2448c61 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psd1 @@ -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 = '' + + # 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 = @() + + # 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 = '' + +} + diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psm1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psm1 new file mode 100644 index 0000000..598fa57 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/ITD.Shared-ServiceNow.psm1 @@ -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 \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Private/Get-ITDServiceNowVariable.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Private/Get-ITDServiceNowVariable.ps1 new file mode 100644 index 0000000..f4c13e3 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Private/Get-ITDServiceNowVariable.ps1 @@ -0,0 +1,18 @@ +function Get-ITDServiceNowVariable { + [CmdletBinding()] + param ( + + ) + + begin { + + } + + process { + + } + + end { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Complete-ITDServiceNowChangeRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Complete-ITDServiceNowChangeRequest.ps1 new file mode 100644 index 0000000..741f40d --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Complete-ITDServiceNowChangeRequest.ps1 @@ -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 { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowChangeTemplateStandard.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowChangeTemplateStandard.ps1 new file mode 100644 index 0000000..3086143 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowChangeTemplateStandard.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowRecord.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowRecord.ps1 new file mode 100644 index 0000000..ba92e90 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowRecord.ps1 @@ -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 { + + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowSession.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowSession.ps1 new file mode 100644 index 0000000..b5750e9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowSession.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowTable.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowTable.ps1 new file mode 100644 index 0000000..b91c153 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowTable.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUser.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUser.ps1 new file mode 100644 index 0000000..22d488a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUser.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUserGroup.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUserGroup.ps1 new file mode 100644 index 0000000..168f8f2 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Get-ITDServiceNowUserGroup.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequest.ps1 new file mode 100644 index 0000000..30715c0 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequest.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequestOG.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequestOG.ps1 new file mode 100644 index 0000000..40bc4b1 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowChangeRequestOG.ps1 @@ -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 + } +} + diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowIncident.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowIncident.ps1 new file mode 100644 index 0000000..b70893a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowIncident.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowRecord.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowRecord.ps1 new file mode 100644 index 0000000..c8fdcd5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowRecord.ps1 @@ -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 +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowServiceCatalogRequest.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowServiceCatalogRequest.ps1 new file mode 100644 index 0000000..be70e32 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowServiceCatalogRequest.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowSession.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowSession.ps1 new file mode 100644 index 0000000..b699eed --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/New-ITDServiceNowSession.ps1 @@ -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" +#> \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Update-ITDServiceNowRecord.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Update-ITDServiceNowRecord.ps1 new file mode 100644 index 0000000..48e8995 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Public/Update-ITDServiceNowRecord.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/API_Examples.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/API_Examples.ps1 new file mode 100644 index 0000000..8451bd9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/API_Examples.ps1 @@ -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 \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB tags key values.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB tags key values.ps1 new file mode 100644 index 0000000..b81a4a9 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB tags key values.ps1 @@ -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 +} + diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB_CI custom variable examples.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB_CI custom variable examples.ps1 new file mode 100644 index 0000000..4ebacf5 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/CMDB_CI custom variable examples.ps1 @@ -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 + diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Compare-ITDVMSharePointToCmdb.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Compare-ITDVMSharePointToCmdb.ps1 new file mode 100644 index 0000000..f67228f --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Compare-ITDVMSharePointToCmdb.ps1 @@ -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 + } +} \ No newline at end of file diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Complete-ITDServiceNowIncident.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Complete-ITDServiceNowIncident.ps1 new file mode 100644 index 0000000..4bfeb15 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Complete-ITDServiceNowIncident.ps1 @@ -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'; + } +} diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Function_Examples.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Function_Examples.ps1 new file mode 100644 index 0000000..36772e8 --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Function_Examples.ps1 @@ -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") + + + + diff --git a/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Get-ITDVMSharePointCmdbDiff.ps1 b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Get-ITDVMSharePointCmdbDiff.ps1 new file mode 100644 index 0000000..9d66b1a --- /dev/null +++ b/_NDGOV_WindowsTeam/ITD.Shared-ServiceNow/Scripts/Get-ITDVMSharePointCmdbDiff.ps1 @@ -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 + } +} \ No newline at end of file