This commit is contained in:
Zack Meier
2026-04-15 15:45:50 -05:00
commit 1d304511b8
613 changed files with 140998 additions and 0 deletions
@@ -0,0 +1,49 @@
trigger:
- main
name: 'ITD.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'
@@ -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 '<ModuleVersion>', $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 "<FunctionsToExport>", $funcStrings
$manifestContent | Set-Content -Path $manifestPath
@@ -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 {
}
}
@@ -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 '^.+?(?<!\\),', ''
}
Else {
Write-Error "AD object already exists, OU path mismatch"
Exit
Exit
}
}
Else {
switch ($Environment) {
'Test' {
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
Else { $EnvString = "Test" }
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
}
'Production' {
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Prod" }
Else { $EnvString = "Prod" }
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
}
}
If ($OuAppNameEnv) { $OUFinal = $OUAppNameEnv.DistinguishedName }
Else { $OuFinal = $OUAppName.DistinguishedName }
}
}
# 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 $IpAddress) {
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"
}
}
}
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 {
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>ITD.ITD-WindowsServer.General</id>
<version>$VERSIONHERE$</version>
<authors>Zack Meier</authors>
<description>Functions for Windows Server General administration</description>
</metadata>
<files>
<file src="**" exclude="**\.git\**;**\Build\**" />
</files>
</package>
@@ -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 = '<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 = @(<FunctionsToExport>)
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
@@ -0,0 +1,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
@@ -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 {
}
}
@@ -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 {
}
}
@@ -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 {
}
}
@@ -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)
@@ -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