Skip to content

Commit

Permalink
save latest changes from testing
Browse files Browse the repository at this point in the history
  • Loading branch information
arudell committed Apr 19, 2024
1 parent 46e8a52 commit f233e66
Show file tree
Hide file tree
Showing 18 changed files with 374 additions and 400 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function Confirm-IsCertSelfSigned {
)

if ($Certificate.Issuer -eq $Certificate.Subject) {
"Detected the certificate subject and issuer are the same. Setting SelfSigned to true" | Trace-Output -Level:Verbose
return $true
}

Expand Down
188 changes: 61 additions & 127 deletions src/modules/SdnDiag.Common/private/Copy-CertificateToFabric.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ function Copy-CertificateToFabric {
$Credential = [System.Management.Automation.PSCredential]::Empty
)

$createRemoteDirectorySB = {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
New-Item -Path $param1 -ItemType Directory -Force
}
}

# scriptblock to import the certificate
# this function will automatically install the certificate to the localmachine\root cert directory
# if the certificate passed to it is self-signed and it is being installed to localmachine\my cert directory
$importCertSB = {
param([Parameter(Position = 0)][String]$param1, [Parameter(Position = 1)][SecureString]$param2, [Parameter(Position = 2)][String]$param3)
Import-SdnCertificate -FilePath $param1 -CertPassword $param2 -CertStore $param3
}

# if we are installing the rest certificate and need to seed certificate to southbound devices
# then define the variables to know which nodes must be updated
if ($PSCmdlet.ParameterSetName -ieq 'NetworkControllerRest' -and $InstallToSouthboundDevices) {
Expand All @@ -57,6 +72,8 @@ function Copy-CertificateToFabric {
}

$certFileInfo = Get-Item -Path $CertFile -ErrorAction Stop
[System.String]$remoteFilePath = Join-Path -Path $certFileInfo.Directory.FullName -ChildPath $certFileInfo.Name

switch ($certFileInfo.Extension) {
'.pfx' {
if ($CertPassword) {
Expand All @@ -79,151 +96,68 @@ function Copy-CertificateToFabric {

switch ($PSCmdlet.ParameterSetName) {
'LoadBalancerMuxNode' {
foreach ($controller in $FabricDetails.NetworkController) {
# if the certificate being passed is self-signed, we will need to copy the certificate to the other controller nodes
# within the fabric and install under localmachine\root as appropriate
if ($certData.Subject -ieq $certData.Issuer) {
"Importing certificate [Subject: {0} Thumbprint:{1}] to {2}" -f `
$certData.Subject, $certData.Thumbprint, $controller | Trace-Output

[System.String]$remoteFilePath = Join-Path -Path $certFileInfo.Directory.FullName -ChildPath $certFileInfo.Name
$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
New-Item -Path $param1 -ItemType Directory -Force
}
} -ArgumentList $certFileInfo.Directory.FullName

Copy-FileToRemoteComputer -ComputerName $controller -Credential $Credential -Path $certFileInfo.FullName -Destination $remoteFilePath

$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1, [Parameter(Position = 1)][SecureString]$param2, [Parameter(Position = 2)][String]$param3)
Import-SdnCertificate -FilePath $param1 -CertPassword $param2 -CertStore $param3
} -ArgumentList @($remoteFilePath, $CertPassword, 'Cert:\LocalMachine\Root') -ErrorAction Stop
}

else {
"No action required for {0}" -f $certData.Thumbprint | Trace-Output -Level:Verbose
}
if (Confirm-IsCertSelfSigned -Certificate $certData) {
$certStore = 'Cert:\LocalMachine\Root'
$computersToInstallCert = $FabricDetails.NetworkController
}
}

'NetworkControllerRest' {
# copy the pfx certificate for the rest certificate to all network controllers within the cluster
# and import to localmachine\my cert directory
foreach ($controller in $FabricDetails.NetworkController) {
"Processing {0}" -f $controller | Trace-Output -Level:Verbose

"[REST CERT] Importing certificate [Subject: {0} Thumbprint:{1}] to {2}" -f `
$certData.Subject, $certData.Thumbprint, $controller | Trace-Output

if (Test-ComputerNameIsLocal -ComputerName $controller) {
$importCert = Import-SdnCertificate -FilePath $certFileInfo.FullName -CertPassword $CertPassword -CertStore 'Cert:\LocalMachine\My'

# if the certificate was detected as self signed
# we will then copy the .cer file returned from the previous command to all the southbound nodes to install
if ($importCert.SelfSigned -and $InstallToSouthboundDevices) {
Install-SdnDiagnostics -ComputerName $southBoundNodes -Credential $Credential -ErrorAction Stop

"[REST CERT] Installing self-signed certificate to southbound devices" | Trace-Output
Invoke-PSRemoteCommand -ComputerName $southBoundNodes -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
$null = New-Item -Path $param1 -ItemType Directory -Force
}
} -ArgumentList $importCert.CerFileInfo.Directory.FullName

foreach ($sbNode in $southBoundNodes) {
"[REST CERT] Installing self-signed certificate to {0}" -f $sbNode | Trace-Output
Copy-FileToRemoteComputer -ComputerName $sbNode -Credential $Credential -Path $importCert.CerFileInfo.FullName -Destination $importCert.CerFileInfo.FullName
$null = Invoke-PSRemoteCommand -ComputerName $sbNode -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1,[Parameter(Position = 1)][String]$param2)
Import-SdnCertificate -FilePath $param1 -CertStore $param2
} -ArgumentList @($importCert.CerFileInfo.FullName, 'Cert:\LocalMachine\Root') -ErrorAction Stop
}
}
if (Confirm-IsCertSelfSigned -Certificate $certData) {
if ($InstallToSouthboundDevices) {
# for southbound devices, if the certificate is self-signed, we will install the certificate under the localmachine\root cert directory
$certStore = 'Cert:\LocalMachine\Root'
$computersToInstallCert = $southBoundNodes
}
else {
[System.String]$remoteFilePath = Join-Path -Path $certFileInfo.Directory.FullName -ChildPath $certFileInfo.Name
$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
New-Item -Path $param1 -ItemType Directory -Force
}
} -ArgumentList $certFileInfo.Directory.FullName

Copy-FileToRemoteComputer -ComputerName $controller -Credential $Credential -Path $certFileInfo.FullName -Destination $remoteFilePath

$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1, [Parameter(Position = 1)][SecureString]$param2, [Parameter(Position = 2)][String]$param3)
Import-SdnCertificate -FilePath $param1 -CertPassword $param2 -CertStore $param3
} -ArgumentList @($remoteFilePath, $CertPassword, 'Cert:\LocalMachine\My')
# for network controller, we will install the certificate under the localmachine\my cert directory
$certStore = 'Cert:\LocalMachine\My'
$computersToInstallCert = $FabricDetails.NetworkController
}
}
}

'NetworkControllerNode' {
foreach ($controller in $FabricDetails.NetworkController) {
"Processing {0}" -f $controller | Trace-Output -Level:Verbose

# if the certificate being passed is self-signed, we will need to copy the certificate to the other controller nodes
# within the fabric and install under localmachine\root as appropriate
if ($certData.Subject -ieq $certData.Issuer) {
"Importing certificate [Subject: {0} Thumbprint:{1}] to {2}" -f `
$certData.Subject, $certData.Thumbprint, $controller | Trace-Output

[System.String]$remoteFilePath = Join-Path -Path $certFileInfo.Directory.FullName -ChildPath $certFileInfo.Name
$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
New-Item -Path $param1 -ItemType Directory -Force
}
} -ArgumentList $certFileInfo.Directory.FullName

Copy-FileToRemoteComputer -ComputerName $controller -Credential $Credential -Path $certFileInfo.FullName -Destination $remoteFilePath

$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1, [Parameter(Position = 1)][SecureString]$param2, [Parameter(Position = 2)][String]$param3)
Import-SdnCertificate -FilePath $param1 -CertPassword $param2 -CertStore $param3
} -ArgumentList @($remoteFilePath, $CertPassword, 'Cert:\LocalMachine\Root') -ErrorAction Stop
}

else {
"No action required for {0}" -f $certData.Thumbprint | Trace-Output -Level:Verbose
}
if (Confirm-IsCertSelfSigned -Certificate $certData) {
$certStore = 'Cert:\LocalMachine\Root'
$computersToInstallCert = $FabricDetails.NetworkController
}
}

# for ServerNodes, we must distribute the server certificate and install to the cert:\localmachine\root directory on each of the
# network controller nodes
'ServerNode' {
foreach ($controller in $FabricDetails.NetworkController) {
# if the certificate being passed is self-signed, we will need to copy the certificate to the other controller nodes
# within the fabric and install under localmachine\root as appropriate
if ($certData.Subject -ieq $certData.Issuer) {
"Importing certificate [Subject: {0} Thumbprint:{1}] to {2}" -f `
$certData.Subject, $certData.Thumbprint, $controller | Trace-Output

[System.String]$remoteFilePath = Join-Path -Path $certFileInfo.Directory.FullName -ChildPath $certFileInfo.Name
$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)
if (-NOT (Test-Path -Path $param1 -PathType Container)) {
New-Item -Path $param1 -ItemType Directory -Force
}
} -ArgumentList $certFileInfo.Directory.FullName

Copy-FileToRemoteComputer -ComputerName $controller -Credential $Credential -Path $certFileInfo.FullName -Destination $remoteFilePath

$null = Invoke-PSRemoteCommand -ComputerName $controller -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1, [Parameter(Position = 1)][SecureString]$param2, [Parameter(Position = 2)][String]$param3)
Import-SdnCertificate -FilePath $param1 -CertPassword $param2 -CertStore $param3
} -ArgumentList @($remoteFilePath, $CertPassword, 'Cert:\LocalMachine\Root') -ErrorAction Stop
}

else {
"No action required for {0}" -f $certData.Thumbprint | Trace-Output -Level:Verbose
}
if (Confirm-IsCertSelfSigned -Certificate $certData) {
$certStore = 'Cert:\LocalMachine\Root'
$computersToInstallCert = $FabricDetails.NetworkController
}
}
}

# create the remote directory we need to copy certificate to
Invoke-PSRemoteCommand @{
ComputerName = $computersToInstallCert
Credential = $Credential
ScriptBlock = $createRemoteDirectorySB
ArgumentList = @($certFileInfo.Directory.FullName)
ErrorAction = 'Stop'
}

# copy the file
Copy-FileToRemoteComputer @{
ComputerName = $computersToInstallCert
Credential = $Credential
Path = $certFileInfo.FullName
Destination = $remoteFilePath
ErrorAction = 'Stop'
}

# import the certificate
Invoke-PSRemoteCommand @{
ComputerName = $computersToInstallCert
Credential = $Credential
ScriptBlock = $importCertSB
ArgumentList = @($remoteFilePath, $CertPassword, $certStore)
ErrorAction = 'Stop'
}
}
10 changes: 10 additions & 0 deletions src/modules/SdnDiag.Common/public/Get-SdnCertificate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,22 @@ function Get-SdnCertificate {

try {
$certificateList = Get-ChildItem -Path $Path | Where-Object {$_.PSISContainer -eq $false} -ErrorAction Ignore
if ($null -eq $certificateList) {
return $null
}

if ($NetworkControllerOid) {
$certificateList | ForEach-Object {
if ($objectIdentifier -iin $_.EnhancedKeyUsageList.ObjectId) {
$array += $_
}
}

# if no certificates are found based on the OID, search based on other criteria
if (!$array) {
"Unable to locate certificates that match Network Controller OID: {0}. Searching based on other criteria." -f $objectIdentifier | Trace-Output -Level:Warning
$array = $certificateList
}
}
else {
$array = $certificateList
Expand Down
7 changes: 3 additions & 4 deletions src/modules/SdnDiag.Common/public/Import-SdnCertificate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function Import-SdnCertificate {
$certObject = [PSCustomObject]@{
SelfSigned = $false
CertInfo = $null
CerFileInfo = $null
SelfSignedCertFileInfo = $null
}

try {
Expand Down Expand Up @@ -73,8 +73,7 @@ function Import-SdnCertificate {
}

# determine if the certificates being used are self signed
if ($certObject.CertInfo.Subject -ieq $certObject.CertInfo.Issuer) {
"Detected the certificate subject and issuer are the same. Setting SelfSigned to true" | Trace-Output -Level:Verbose
if (Confirm-IsCertSelfSigned -Certificate $certObject.CertInfo) {
$certObject.SelfSigned = $true

# check to see if we installed to root store with above operation
Expand All @@ -84,7 +83,7 @@ function Import-SdnCertificate {
$selfSignedCerExists = Get-SdnCertificate -Path $trustedRootStore -Thumbprint $certObject.CertInfo.Thumbprint
[System.String]$selfSignedCerPath = "{0}\{1}.cer" -f (Split-Path $fileInfo.FullName -Parent), ($certObject.CertInfo.Subject).Replace('=','_')
$selfSignedCer = Export-Certificate -Cert $certObject.CertInfo -FilePath $selfSignedCerPath -ErrorAction Stop
$certObject.CerFileInfo = $selfSignedCer
$certObject.SelfSignedCertFileInfo = $selfSignedCer

if (-NOT ($selfSignedCerExists)) {
# import the certificate to the trusted root store
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ function Start-SdnMuxCertificateRotation {

[CmdletBinding(DefaultParameterSetName = 'GenerateCertificate')]
param (
[Parameter(Mandatory = $false, ParameterSetName = 'GenerateCertificate')]
[System.String]$NetworkController = $env:COMPUTERNAME,
[Parameter(Mandatory = $true, ParameterSetName = 'GenerateCertificate')]
[System.String]$NetworkController,

[Parameter(Mandatory = $true, ParameterSetName = 'GenerateCertificate')]
[System.Management.Automation.PSCredential]
Expand All @@ -45,16 +45,7 @@ function Start-SdnMuxCertificateRotation {
)

# ensure that the module is running as local administrator
$elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-NOT $elevated) {
throw New-Object System.Exception("This function requires elevated permissions. Run PowerShell as an Administrator and import the module again.")
}

$config = Get-SdnModuleConfiguration -Role 'NetworkController'
$confirmFeatures = Confirm-RequiredFeaturesInstalled -Name $config.windowsFeature
if (-NOT ($confirmFeatures)) {
throw New-Object System.NotSupportedException("The current machine is not a NetworkController, run this on NetworkController.")
}
Confirm-IsAdmin

$array = @()
$headers = @{"Accept"="application/json"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class BaseCert {
[bool]$IsSelfSigned
}

class RestCert : BaseCert {
[CertType]$CertificateType = [CertType]::Rest
class RestCertificate : BaseCert {
[CertType]$CertificateType = [CertType]::RestCertificate
}

class NodeCert : BaseCert {
Expand All @@ -27,19 +27,19 @@ class NodeCert : BaseCert {
}

class NetworkControllerNodeCert : NodeCert {
[CertType]$CertificateType = [CertType]::NetworkController
[CertType]$CertificateType = [CertType]::NetworkControllerNodeCert
}

class LoadBalancerMuxNodeCert : NodeCert {
[CertType]$CertificateType = [CertType]::LoadBalancerMux
[CertType]$CertificateType = [CertType]::LoadBalancerMuxNodeCert
}

class ServerNodeCert : NodeCert {
[CertType]$CertificateType = [CertType]::Server
[CertType]$CertificateType = [CertType]::ServerNodeCert
}

class CertRotateConfig {
[RestCert]$RestCert
[RestCertificate]$RestCertificate
[ClusterCredentialType]$ClusterCredentialType = [ClusterCredentialType]::Kerberos
[Object[]]$NodeCerts
}
Expand All @@ -50,10 +50,10 @@ enum ClusterCredentialType {
}

enum CertType {
Rest
NetworkController
Server
LoadBalancerMux
RestCertificate
NetworkControllerNodeCert
ServerNodeCert
LoadBalancerMuxNodeCert
}

enum NcManagedRoles {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function Confirm-IsNetworkController {
$config = Get-SdnModuleConfiguration -Role 'NetworkController'
$confirmFeatures = Confirm-RequiredFeaturesInstalled -Name $config.windowsFeature
if (-NOT ($confirmFeatures)) {
throw New-Object System.NotSupportedException("The current machine is not a NetworkController, run this on NetworkController.")
}
}
Loading

0 comments on commit f233e66

Please sign in to comment.