Skip to content

Commit

Permalink
Add cOctopusServerGuestAuthentication resource
Browse files Browse the repository at this point in the history
To enable/disable guest login
  • Loading branch information
matt-richardson committed Aug 11, 2017
1 parent 1b26302 commit 3b0a50d
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
$octopusServerExePath = "$($env:ProgramFiles)\Octopus Deploy\Octopus\Octopus.Server.exe"

function Get-TargetResource
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")]
[OutputType([Hashtable])]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]$InstanceName,
[Parameter(Mandatory)]
[boolean]$Enabled
)
# check octopus installed
if (-not (Test-Path -LiteralPath $octopusServerExePath)) {
throw "Unable to find Octopus (checked for existance of file '$octopusServerExePath')."
}
# check octopus version >= 3.5.0
if (-not (Test-OctopusVersionSupportsAuthenticationProviders)) {
throw "This resource only supports Octopus Deploy 3.5.0+."
}

$config = Get-Configuration $InstanceName

$result = @{
InstanceName = $InstanceName
Enabled = $config.Octopus.WebPortal.GuestLoginEnabled
}

return $result
}

function Set-TargetResource
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]$InstanceName,
[Parameter(Mandatory)]
[boolean]$Enabled
)
$args = @(
'configure',
'--console',
'--instance', $InstanceName,
'--guestLoginEnabled', $Enabled
)
Invoke-OctopusServerCommand $args
}

function Test-TargetResource
{
[OutputType([boolean])]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]$InstanceName,
[Parameter(Mandatory)]
[boolean]$Enabled
)
$currentResource = (Get-TargetResource -InstanceName $InstanceName `
-Enabled $Enabled)

$params = Get-Parameters $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 Get-Configuration($instanceName)
{
$rawConfig = & $octopusServerExePath show-configuration --format=json-hierarchical --noconsolelogging --console --instance $instanceName
$config = $rawConfig | ConvertFrom-Json
return $config
}

function Invoke-OctopusServerCommand ($arguments)
{
Write-Log "Executing command '$octopusServerExePath $($arguments -join ' ')'"
$output = .$octopusServerExePath $arguments

Write-CommandOutput $output
if (($null -ne $LASTEXITCODE) -and ($LASTEXITCODE -ne 0)) {
Write-Error "Command returned exit code $LASTEXITCODE. Aborting."
exit 1
}
Write-Log "done."
}

function Write-CommandOutput
{
param (
[string] $output
)

if ($output -eq "") { return }

Write-Verbose ""
#this isn't quite working
foreach($line in $output.Trim().Split("`n"))
{
Write-Verbose $line
}
Write-Verbose ""
}

function Test-OctopusVersionSupportsAuthenticationProviders
{
if (-not (Test-Path -LiteralPath $octopusServerExePath))
{
throw "Octopus.Server.exe path '$octopusServerExePath' does not exist."
}

$exeFile = Get-Item -LiteralPath $octopusServerExePath -ErrorAction Stop
if ($exeFile -isnot [System.IO.FileInfo])
{
throw "Octopus.Server.exe path '$octopusServerExePath ' does not refer to a file."
}

$fileVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($octopusServerExePath).FileVersion
$octopusServerVersion = New-Object System.Version $fileVersion
$versionWhereAuthenticationProvidersWereIntroduced = New-Object System.Version 3, 5, 0

return ($octopusServerVersion -ge $versionWhereAuthenticationProvidersWereIntroduced)
}

function Get-Parameters($parameters)
{
# unfortunately $PSBoundParameters doesn't contain parameters that weren't supplied (because the default value was okay)
# credit to https://www.briantist.com/how-to/splatting-psboundparameters-default-values-optional-parameters/
$params = @{}
foreach($h in $parameters.GetEnumerator()) {
$key = $h.Key
$var = Get-Variable -Name $key -ErrorAction SilentlyContinue
if ($null -ne $var)
{
$val = Get-Variable -Name $key -ErrorAction Stop | Select-Object -ExpandProperty Value -ErrorAction Stop
$params[$key] = $val
}
}
return $params
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[ClassVersion("1.0.0"), FriendlyName("cOctopusServerGuestAuthentication")]
class cOctopusServerGuestAuthentication : OMI_BaseResource
{
[Key, Description("Name of the Octopus Server instance")] string InstanceName;
[Write] boolean Enabled;
};
13 changes: 13 additions & 0 deletions OctopusDSC/Examples/cOctopusServerGuestAuthentication.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Configuration SampleConfig
{
Import-DscResource -Module OctopusDSC

Node "localhost"
{
cOctopusServerGuestAuthentication "Enable Guest Authentication"
{
InstanceName = "OctopusServer"
Enabled = $true
}
}
}
91 changes: 91 additions & 0 deletions OctopusDSC/Tests/cOctopusServerGuestAuthentication.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#requires -Version 4.0

$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 {

Describe 'cOctopusServerGuestAuthentication' {
BeforeEach {
$desiredConfiguration = @{
InstanceName = 'OctopusServer'
Enabled = $true
}
}

Context 'Get-TargetResource' {
It 'Returns the proper data' {
Mock Test-Path { return $true } -ParameterFilter { $LiteralPath -eq "$($env:ProgramFiles)\Octopus Deploy\Octopus\Octopus.Server.exe" }
Mock Test-OctopusVersionSupportsAuthenticationProviders { return $true }
Mock Get-Configuration { return @{Octopus = @{ WebPortal = @{ GuestLoginEnabled = $true }}} }

$config = Get-TargetResource @desiredConfiguration
$config.InstanceName | Should Be 'OctopusServer'
$config.Enabled | Should Be $true
}

It 'Throws an exception if Octopus is not installed' {
Mock Test-Path { return $false } -ParameterFilter { $LiteralPath -eq "$($env:ProgramFiles)\Octopus Deploy\Octopus\Octopus.Server.exe" }
Mock Test-OctopusVersionSupportsAuthenticationProviders { return $true }
{ Get-TargetResource @desiredConfiguration } | Should Throw "Unable to find Octopus (checked for existance of file '$octopusServerExePath')."
}

It 'Throws an exception if its an old version of Octopus' {
Mock Test-Path { return $true } -ParameterFilter { $LiteralPath -eq "$($env:ProgramFiles)\Octopus Deploy\Octopus\Octopus.Server.exe" }
Mock Test-OctopusVersionSupportsAuthenticationProviders { return $false }
{ Get-TargetResource @desiredConfiguration } | Should Throw "This resource only supports Octopus Deploy 3.5.0+."
}
}

Context 'Test-TargetResource' {
$response = @{ InstanceName="OctopusServer"; Enabled=$true }
Mock Get-TargetResource { return $response }

It 'Returns True when its currently enabled' {
$desiredConfiguration['InstanceName'] = 'OctopusServer'
$desiredConfiguration['Enabled'] = $true
$response['InstanceName'] = 'OctopusServer'
$response['Enabled'] = $true

Test-TargetResource @desiredConfiguration | Should Be $true
}

It 'Returns false when its currently disabled' {
$desiredConfiguration['InstanceName'] = 'OctopusServer'
$desiredConfiguration['Enabled'] = $true
$response['InstanceName'] = 'OctopusServer'
$response['Enabled'] = $false

Test-TargetResource @desiredConfiguration | Should Be $false
}

It 'Calls Get-TargetResource (and therefore inherits its checks)' {
Test-TargetResource @desiredConfiguration
Assert-MockCalled Get-TargetResource
}
}

Context 'Set-TargetResource' {
It 'Calls Invoke-OctopusServerCommand with the correct arguments' {
Mock Invoke-OctopusServerCommand

Set-TargetResource -InstanceName 'SuperOctopus' -Enabled $false
Assert-MockCalled Invoke-OctopusServerCommand -ParameterFilter { ($arguments -join ' ') -eq 'configure --console --instance SuperOctopus --guestLoginEnabled false'}
}
}
}
}
}
finally
{
if ($module) {
Remove-Module -ModuleInfo $module
}
}
34 changes: 34 additions & 0 deletions README-cOctopusServerGuestAuthentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# README-cOctopusServerGuestAuthentication

## 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"
{
cOctopusServerGuestAuthentication "Enable guest account login"
{
InstanceName = "OctopusServer"
Enabled = $true
}
}
}
SampleConfig
Start-DscConfiguration .\SampleConfig -Verbose -wait
Test-DscConfiguration
```

## Properties

| Property | Type | Default Value | Description |
| --------------------| ------------ | -----------------| ------------|
| `InstanceName` | `string` | | The name of the Octopus Server instance. Use `OctopusServer` by convention unless you have more than one instance. |
| `Enabled` | `boolean` | `$false` | Whether to enable the read-only guest account. |
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

This repository contains a PowerShell module with DSC resources that can be used to install and configure an [Octopus Deploy](http://octopusdeploy.com) Server and Tentacle agent.

Read about the [cTentacleAgent](README-cTentacleAgent.md) or [cOctopusServer](README-cOctopusServer.md) resources.
There are two main resources:

Authentication can be configured to use:
* [cOctopusServer](README-cOctopusServer.md) to install and configure an Octopus Server, and
* [cTentacleAgent](README-cTentacleAgent.md) to install and configure a Tentacle.

* Active Directory Domain with [cOctopusServerActiveDirectoryAuthentication](README-cOctopusServerActiveDirectoryAuthentication.md)
Server authentication can be configured to use:

* Active Directory with [cOctopusServerActiveDirectoryAuthentication](README-cOctopusServerActiveDirectoryAuthentication.md)
* Azure AD with [cOctopusServerAzureADAuthentication](README-cOctopusServerAzureADAuthentication.md)
* GoogleApps with [cOctopusServerGoogleAppsAuthentication](README-cOctopusServerGoogleAppsAuthentication.md)
* Okta with [cOctopusServerOktaAuthentication](README-cOctopusServerOktaAuthentication.md)
* Username/passwords stored in Octopus with [cOctopusServerUsernamePasswordAuthentication](README-cOctopusServerUsernamePasswordAuthentication.md)
* Read-only guest account login with [cOctopusServerGuestAuthentication](README-cOctopusServerGuestAuthentication.md)

## Development

Expand Down
6 changes: 6 additions & 0 deletions Tests/Server_Scenario_01_Install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ Configuration Server_Scenario_01_Install
Enabled = $true
}

cOctopusServerGuestAuthentication "Enable Guest Login"
{
InstanceName = "OctopusServer"
Enabled = $true
}

cOctopusServerActiveDirectoryAuthentication "Enable Active Directory Auth"
{
InstanceName = "OctopusServer"
Expand Down

0 comments on commit 3b0a50d

Please sign in to comment.