-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial commit * Functional component * Adding Pester tests * Adding tests to new resource * Had some issues in tests * Fixed linting errors and added example * Fixed tests for all authentication methods. The global variable of '' seemed to be unavailable in the BeforeAll, added path resolution here and it worked. * Implementing suggested changes. * More changes * Revert "Fixed tests for all authentication methods. The global variable of '' seemed to be unavailable in the BeforeAll, added path resolution here and it worked." This reverts commit 6beee01. * Implementing suggested changes. * Changing cOctopusServerSslCertificate.Tests from Context to Describe blocks. * Adding readme for new resource * Adding referenced to new readme from main readme * Adding e2e tests for OctopusServerSslCertificate resource. * Aligning code, removed commented out code. * Update OctopusDSC/DSCResources/cOctopusServerSslCertificate/cOctopusServerSslCertificate.psm1 Co-authored-by: Matt Richardson <[email protected]> * Update OctopusDSC/DSCResources/cOctopusServerSslCertificate/cOctopusServerSslCertificate.psm1 Co-authored-by: Matt Richardson <[email protected]> * Update OctopusDSC/Tests/cOctopusServerSslCertificate.Tests.ps1 Co-authored-by: Matt Richardson <[email protected]> * Update README-cOctopusServerSslCertificate.md Co-authored-by: Matt Richardson <[email protected]> * Update README-cOctopusServerSslCertificate.md Co-authored-by: Matt Richardson <[email protected]> * Update OctopusDSC/Examples/cOctopusServerSslCertificate.ps1 Co-authored-by: Matt Richardson <[email protected]> Co-authored-by: Matt Richardson <[email protected]>
- Loading branch information
1 parent
fc0eef8
commit f1adca6
Showing
11 changed files
with
403 additions
and
3 deletions.
There are no files selected for viewing
146 changes: 146 additions & 0 deletions
146
OctopusDSC/DSCResources/cOctopusServerSslCertificate/cOctopusServerSslCertificate.psm1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# dot-source the helper file (cannot load as a module due to scope considerations) | ||
. (Join-Path -Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -ChildPath 'OctopusDSCHelpers.ps1') | ||
|
||
# This is the Octopus Deploy server Application ID, declared within Octopus Server itself | ||
$octopusServerApplicationId = "{E2096A4C-2391-4BE1-9F17-E353F930E7F1}" | ||
|
||
function Get-CurrentSSLBinding { | ||
param([string] $ApplicationId, | ||
[string]$Port) | ||
|
||
$certificateBindings = (& netsh http show sslcert) | select-object -skip 3 | out-string | ||
$newLine = [System.Environment]::NewLine | ||
$certificateBindings = $certificateBindings -split "$newLine$newLine" | ||
$certificateBindingsList = foreach ($certificateBinding in $certificateBindings) { | ||
if ($certificateBinding -ne "") { | ||
$certificateBinding = $certificateBinding -replace " ", "" -split ": " | ||
[pscustomobject]@{ | ||
IPPort = ($certificateBinding[1] -split "`n")[0] | ||
CertificateThumbprint = ($certificateBinding[2] -split "`n" -replace '[^a-zA-Z0-9]', '')[0] | ||
AppID = ($certificateBinding[3] -split "`n")[0] | ||
CertStore = ($certificateBinding[4] -split "`n")[0] | ||
} | ||
} | ||
} | ||
|
||
return ($certificateBindingsList | Where-Object {($_.AppID.Trim() -eq $ApplicationId) -and ($_.IPPort.Trim() -eq "{0}:{1}" -f "0.0.0.0", $Port) }) | ||
} | ||
|
||
function Get-TargetResource { | ||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] | ||
param ( | ||
[Parameter(Mandatory)] | ||
[string] $InstanceName, | ||
[ValidateSet("Present", "Absent")] | ||
[string] $Ensure = "Present", | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $Thumbprint, | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $StoreName, | ||
[ValidateNotNullOrEmpty()] | ||
[int] $Port = 443 | ||
) | ||
|
||
$existingSSLConfig = (Get-CurrentSSLBinding -ApplicationId $octopusServerApplicationId -Port $Port -IPAddress $IPAddress) | ||
|
||
if ($null -ne $existingSSLConfig) { | ||
$existingSSLPort = [int](($existingSSLConfig.IPPort).Split(":")[1]) | ||
$existingSSLThumbprint = $existingSSLConfig.CertificateThumbprint.Trim() | ||
$existingSSLCertificateStoreName = $existingSSLConfig.CertStore.Trim() | ||
$existingEnsure = "Present" | ||
} | ||
else { | ||
$existingEnsure = "Absent" | ||
} | ||
|
||
$result = @{ | ||
InstanceName = $InstanceName | ||
Ensure = $existingEnsure | ||
Port = $existingSSLPort | ||
StoreName = $existingSSLCertificateStoreName | ||
Thumbprint = $existingSSLThumbprint | ||
} | ||
|
||
return $result | ||
} | ||
|
||
function Test-TargetResource { | ||
param( | ||
[Parameter(Mandatory)] | ||
[string] $InstanceName, | ||
[ValidateSet("Present", "Absent")] | ||
[string] $Ensure = "Present", | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $Thumbprint, | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $StoreName, | ||
[ValidateNotNullOrEmpty()] | ||
[int] $Port = 443 | ||
) | ||
|
||
$currentResource = (Get-TargetResource @PSBoundParameters) | ||
$params = Get-ODSCParameter $MyInvocation.MyCommand.Parameters | ||
|
||
$currentConfigurationMatchesRequestedConfiguration = $true | ||
foreach ($key in $currentResource.Keys) { | ||
$currentValue = $currentResource.Item($key) | ||
$requestedValue = $params.Item($key) | ||
|
||
if ($currentValue -ne $requestedValue) { | ||
Write-Verbose "(FOUND MISMATCH) Configuration parameter '$key' with value '$currentValue' mismatched the specified value '$requestedValue'" | ||
$currentConfigurationMatchesRequestedConfiguration = $false | ||
} | ||
else { | ||
Write-Verbose "Configuration parameter '$key' matches the requested value '$requestedValue'" | ||
} | ||
} | ||
|
||
return $currentConfigurationMatchesRequestedConfiguration | ||
} | ||
|
||
function Set-TargetResource { | ||
param( | ||
[Parameter(Mandatory)] | ||
[string] $InstanceName, | ||
[ValidateSet("Present", "Absent")] | ||
[string] $Ensure = "Present", | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $Thumbprint, | ||
[ValidateNotNullOrEmpty()] | ||
[Parameter(Mandatory)] | ||
[string] $StoreName, | ||
[ValidateNotNullOrEmpty()] | ||
[int] $Port = 443 | ||
) | ||
|
||
if ($Ensure -eq "Present") { | ||
$exeArgs = @( | ||
'ssl-certificate', | ||
'--instance', $Instancename, | ||
'--thumbprint', $Thumbprint, | ||
'--certificate-store', $StoreName, | ||
'--port', $Port | ||
) | ||
|
||
Write-Verbose "Binding certificate ..." | ||
Invoke-OctopusServerCommand $exeArgs | ||
} | ||
else { | ||
$currentBinding = (Get-CurrentSSLBinding -ApplicationId $octopusServerApplicationId -Port $Port -IPAddress $IPAddress) | ||
if ($null -ne $currentBinding) { | ||
Write-Verbose "Removing certificate binding ..." | ||
# ideally, we'd call a command in Octopus.Server for this, but there's no command to do this (at this point) | ||
& netsh http delete sslcert ("{0}:{1}" -f "0.0.0.0", $Port) | ||
$currentBinding = (Get-CurrentSSLBinding -ApplicationId $octopusServerApplicationId -Port $Port -IPAddress $IPAddress) | ||
|
||
if ($null -eq $currentBinding) { | ||
Write-Verbose "Binding successfully removed." | ||
} | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
OctopusDSC/DSCResources/cOctopusServerSslCertificate/cOctopusServerSslCertificate.schema.mof
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[ClassVersion("1.0.0"), FriendlyName("cOctopusServerSslCertificate")] | ||
class cOctopusServerSslCertificate : OMI_BaseResource | ||
{ | ||
[Key, Description("Name of the Octopus Server instance")] string InstanceName; | ||
[Write, Required, Description("Thumbprint of the certificate")] string Thumbprint; | ||
[Write, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure; | ||
[Write, Required, ValueMap{"My", "WebHosting"}, Values{"My", "WebHosting"}] string StoreName; | ||
[Write] uint16 Port; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Binds an SSL certificate to the Octopus Server to allow Octopus to listen over https | ||
|
||
Configuration SampleConfig | ||
{ | ||
Import-DscResource -Module OctopusDSC | ||
|
||
Node "localhost" | ||
{ | ||
cOctopusServerSslCertificate "Bind SSL Certifiate" | ||
{ | ||
InstanceName = "OctopusServer" | ||
Thumbprint = "c42a148bcd3959101f2e7a3d76edb924bff84b6b" | ||
Ensure = "Present" | ||
StoreName = "My" | ||
Port = 443 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
OctopusDSC/Tests/cOctopusServerSslCertificate.Tests.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#requires -Version 4.0 | ||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] # these are tests, not anything that needs to be secure | ||
param() | ||
|
||
$moduleName = Split-Path ($PSCommandPath -replace '\.Tests\.ps1$', '') -Leaf | ||
$modulePath = Split-Path $PSCommandPath -Parent | ||
$modulePath = Resolve-Path "$PSCommandPath/../../DSCResources/$moduleName/$moduleName.psm1" | ||
$module = $null | ||
|
||
try | ||
{ | ||
$prefix = [guid]::NewGuid().Guid -replace '-' | ||
$module = Import-Module $modulePath -Prefix $prefix -PassThru -ErrorAction Stop | ||
|
||
InModuleScope $module.Name { | ||
$sampleConfigPath = Split-Path $PSCommandPath -Parent | ||
$sampleConfigPath = Join-Path $sampleConfigPath "SampleConfigs" | ||
|
||
Describe 'cOctopusServerSslCertificate' { | ||
Describe 'Get-TargetResource - when present and port not specified' { | ||
It 'Returns correct data when SSL binding exists' { | ||
Mock Get-CurrentSSLBinding { | ||
return [PSCustomObject]@{ | ||
IPPort = "0.0.0.0:443" | ||
CertificateThumbprint = "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
AppID = "{E2096A4C-2391-4BE1-9F17-E353F930E7F1}" | ||
CertStore = "My" | ||
} | ||
} | ||
|
||
$result = Get-TargetResource -InstanceName "OctopusServer" ` | ||
-Ensure "Present" ` | ||
-Thumbprint "dfcbdb879e5315e05982c05793e57c39241797e3" ` | ||
-StoreName "My" | ||
|
||
$result.Ensure | Should -Be 'Present' | ||
$result.Port | Should -Be "443" | ||
$result.StoreName | Should -Be "My" | ||
$result.Thumbprint | Should -Be "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
} | ||
} | ||
|
||
Describe 'Get-TargetResource - when present and port specified' { | ||
It 'Returns present and 1443 when SSL binding exists' { | ||
Mock Get-CurrentSSLBinding { | ||
return [PSCustomObject]@{ | ||
IPPort = "0.0.0.0:1443" | ||
CertificateThumbprint = "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
AppID = "{E2096A4C-2391-4BE1-9F17-E353F930E7F1}" | ||
CertStore = "My" | ||
} | ||
} | ||
|
||
$result = Get-TargetResource -InstanceName "OctopusServer" ` | ||
-Ensure "Present" ` | ||
-Thumbprint "dfcbdb879e5315e05982c05793e57c39241797e3" ` | ||
-StoreName "My" ` | ||
-Port "1443" | ||
|
||
$result.Ensure | Should -Be 'Present' | ||
$result.Port | Should -Be "1443" | ||
$result.StoreName | Should -Be "My" | ||
$result.Thumbprint | Should -Be "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
} | ||
} | ||
|
||
Describe 'Get-TargetResource - when absent' { | ||
It 'Returns absent when binding does not exist' { | ||
Mock Get-CurrentSSLBinding { | ||
return $null | ||
} | ||
|
||
$result = Get-TargetResource -InstanceName "OctopusServer" ` | ||
-Ensure "Present" ` | ||
-Thumbprint "dfcbdb879e5315e05982c05793e57c39241797e3" ` | ||
-StoreName "My" | ||
|
||
$result.Ensure | Should -Be "Absent" | ||
$result.StoreName | Should -Be $null | ||
$result.Thumbprint | Should -Be $null | ||
$result.Port | Should -Be $null | ||
} | ||
} | ||
|
||
Describe 'Test-TargetResource - when present' { | ||
It 'Returns false when port differs' { | ||
Mock Get-CurrentSSLBinding { | ||
return [PSCustomObject]@{ | ||
IPPort = "0.0.0.0:443" | ||
CertificateThumbprint = "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
AppID = "{E2096A4C-2391-4BE1-9F17-E353F930E7F1}" | ||
CertStore = "My" | ||
} | ||
|
||
$result = Test-TargetResource -InstanceName "OctopusServer" ` | ||
-Ensure "Present" ` | ||
-Thumbprint "dfcbdb879e5315e05982c05793e57c39241797e3" ` | ||
-StoreName "My" ` | ||
-Port "1443" | ||
|
||
$result | Should -Be $false | ||
} | ||
} | ||
|
||
It 'Returns true when port matches' { | ||
return [PSCustomObject]@{ | ||
IPPort = "0.0.0.0:443" | ||
CertificateThumbprint = "dfcbdb879e5315e05982c05793e57c39241797e3" | ||
AppID = "{E2096A4C-2391-4BE1-9F17-E353F930E7F1}" | ||
CertStore = "My" | ||
} | ||
|
||
$result = Test-TargetResource -InstanceName "OctopusServer" ` | ||
-Ensure "Present" ` | ||
-Thumbprint "dfcbdb879e5315e05982c05793e57c39241797e3" ` | ||
-StoreName "My" ` | ||
-Port "443" | ||
|
||
$result | Should -Be $true | ||
} | ||
} | ||
} | ||
} | ||
} | ||
finally | ||
{ | ||
if ($module) | ||
{ | ||
Remove-Module -ModuleInfo $module | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# README-cOctopusServerSslCertificate | ||
|
||
This resource binds a SSL certificate to allow Octopus Server to listen over HTTPS. | ||
It binds the certificate stored in the Windows Certificate store identified by the `StoreName` and `Thumbprint` to the port that the sever will listen on. | ||
This port must match the https entry in the `WebListenPrefix` element of the cOctopusServer resource. | ||
|
||
## Sample | ||
|
||
First, ensure the OctopusDSC module is on your `$env:PSModulePath`. Then you can create and apply configuration like this. | ||
|
||
```PowerShell | ||
Configuration SampleConfig | ||
{ | ||
Import-DscResource -Module OctopusDSC | ||
Node "localhost" | ||
{ | ||
cOctopusServerSslCertificate SSLCert | ||
{ | ||
InstanceName = "OctopusServer" | ||
Thumbprint = "<Thumbprint string from certificate>" | ||
Ensure = "Present" | ||
StoreName = "My" | ||
Port = 443 | ||
} | ||
} | ||
} | ||
SampleConfig | ||
Start-DscConfiguration .\SampleConfig -Verbose -wait | ||
Test-DscConfiguration | ||
``` | ||
|
||
## Properties | ||
| Property | Type | Default Value | Description | | ||
| ------------------------------------------| ------------------------------- | -----------------| ------------------------------------------------------------------------------------------------------------------ | | ||
| `Ensure` | `string` - `Present` or `Absent`| `Present` | The desired state of the Octopus Server - effectively whether to install or uninstall. | | ||
| `InstanceName` | `string` | | The name of the Octopus Server instance. Use `OctopusServer` by convention unless you have more than one instance. | | ||
| `Thumbprint` | `string` | | Thumbprint of the SSL certificate to use with Octopus Deploy, | | ||
| `StoreName` | `string` - `My` or `WebHosting` | | Which certificate store to look for the thumbprint in. | | ||
| `Port` | `int` | | The port to use SSL on. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.