update
This commit is contained in:
@@ -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
|
||||
+93
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
+694
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
+1037
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
+154
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
+154
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user