diff --git a/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.psm1 b/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.psm1 index 7687335..9fa0637 100644 --- a/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.psm1 +++ b/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.psm1 @@ -23,6 +23,8 @@ function Get-PrefixComputerName { Unused - not necessary for discovery. .PARAMETER LogonCredential Unused - not necessary for discovery. +.PARAMETER IntegratedAuth + Unused - not necessary for discovery. .PARAMETER Ensure Unused - not necessary for discovery. #> @@ -59,7 +61,10 @@ function Get-TargetResource { $Ensure = 'Present', [System.Boolean] - $PrefixComputerName = $false + $PrefixComputerName = $false, + + [Switch] + $IntegratedAuth = $false ) if ( $PrefixComputerName ) { $Name = Get-PrefixComputerName $Name } @@ -94,6 +99,8 @@ function Get-TargetResource { The credential used to auth with VSTS. .PARAMETER LogonCredential What credential should the agent service use? +.PARAMETER IntegratedAuth + Should we use integrated auth instead of PAT? .PARAMETER Ensure Should we ensure the agent exists or that it doesn't? #> @@ -132,7 +139,10 @@ function Set-TargetResource { $Ensure = 'Present', [System.Boolean] - $PrefixComputerName = $false + $PrefixComputerName = $false, + + [Switch] + $IntegratedAuth = $false ) if ( Test-TargetResource @PSBoundParameters ) { return } @@ -144,18 +154,26 @@ function Set-TargetResource { 'Name' = $Name 'Pool' = $Pool 'ServerUrl' = $ServerUrl - 'PAT' = $AccountCredential.Password 'AgentDirectory' = $AgentDirectory 'Replace' = $true } + if ( $Work ) { $installArgs['Work'] = $Work } if ( $LogonCredential ) { $installArgs['LogonCredential'] = $LogonCredential } - + + if ( $IntegratedAuth ) { $installArgs['Integrated'] = $true } + else { $installArgs['PAT'] = $AccountCredential.Password + } Install-VSTSAgent @installArgs } else { - Uninstall-VSTSAgent -Name $Name -AgentDirectory $AgentDirectory -PAT $AccountCredential.Password + if ( $IntegratedAuth ) { + Uninstall-VSTSAgent -Name $Name -AgentDirectory $AgentDirectory -Integrated + } + else { + Uninstall-VSTSAgent -Name $Name -AgentDirectory $AgentDirectory -PAT $AccountCredential.Password + } } } @@ -174,6 +192,8 @@ function Set-TargetResource { Unused - testing does not require credentials. .PARAMETER LogonCredential Unused - agent service logon user is not currently detectable. +.PARAMETER IntegratedAuth + Unused - testing does not require credentials. .PARAMETER Ensure Should the agent be present or absent? #> @@ -213,7 +233,10 @@ function Test-TargetResource { $Ensure = 'Present', [System.Boolean] - $PrefixComputerName = $false + $PrefixComputerName = $false, + + [Switch] + $IntegratedAuth = $false ) if ( $PrefixComputerName ) { $Name = Get-PrefixComputerName $Name } diff --git a/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.schema.mof b/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.schema.mof index 9c67913..92d4dbc 100644 --- a/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.schema.mof +++ b/VSTSAgent/DSCResources/xVSTSAgent/xVSTSAgent.schema.mof @@ -10,6 +10,7 @@ class xVSTSAgent : OMI_BaseResource [Required] String AgentDirectory; [Write] String Work; [Write] Boolean PrefixComputerName; + [Write] Boolean IntegratedAuth; [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; }; diff --git a/VSTSAgent/VSTSAgent.psm1 b/VSTSAgent/VSTSAgent.psm1 index 55c5dbb..98838ac 100644 --- a/VSTSAgent/VSTSAgent.psm1 +++ b/VSTSAgent/VSTSAgent.psm1 @@ -186,6 +186,8 @@ function Find-VSTSAgent { What pool should the agent be registered into? .PARAMETER PAT What personal access token (PAT) should be used to auth with VSTS? +.PARAMETER Integrated + Should the agent use integrated auth with VSTS instead of a PAT? .PARAMETER ServerUrl What server url should the agent be registered to? Eg. 'https://account.visualstudio.com' .PARAMETER Replace @@ -222,9 +224,12 @@ function Install-VSTSAgent { [parameter(Mandatory = $false)] [string]$Pool = 'Default', - [parameter(Mandatory = $true)] + [parameter(Mandatory = $true, ParameterSetName = 'PATAuth')] [securestring]$PAT, + [parameter(Mandatory = $true, ParameterSetName = 'IntegratedAuth')] + [switch]$Integrated, + [parameter(Mandatory = $true)] [uri]$ServerUrl, @@ -247,7 +252,12 @@ function Install-VSTSAgent { $existing = Get-VSTSAgent -AgentDirectory $AgentDirectory -NameFilter $Name if ( $existing ) { if ($Replace) { - Uninstall-VSTSAgent -NameFilter $Name -AgentDirectory $AgentDirectory -PAT $PAT -ErrorAction Stop + if ($Integrated) { + Uninstall-VSTSAgent -NameFilter $Name -AgentDirectory $AgentDirectory -Integrated -ErrorAction Stop + } + else { + Uninstall-VSTSAgent -NameFilter $Name -AgentDirectory $AgentDirectory -PAT $PAT -ErrorAction Stop + } } else { throw "Agent $Name already exists in $AgentDirectory" } } @@ -291,16 +301,21 @@ function Install-VSTSAgent { $configPath = Get-ChildItem $configPath -ErrorAction SilentlyContinue if ( -not $configPath ) { throw "Agent $agentFolder is missing config.cmd" } - [string[]]$configArgs = @('--unattended', '--url', "$ServerUrl", '--auth', ` - 'pat', '--pool', "$Pool", '--agent', "$Name", '--runAsService') + [string[]]$configArgs = @('--unattended', '--url', """$ServerUrl""", '--pool',` + """$Pool""", '--agent', """$Name""", '--runAsService') if ( $Replace ) { $configArgs += '--replace' } if ( $LogonCredential ) { $configArgs += '--windowsLogonAccount', $LogonCredential.UserName } - if ( $Work ) { $configArgs += '--work', $Work } + if ( $Work ) { $configArgs += '--work', """$Work""" } if ( -not $PSCmdlet.ShouldProcess("$configPath $configArgs", "Start-Process") ) { return } - $token = [System.Net.NetworkCredential]::new($null, $PAT).Password - $configArgs += '--token', $token + if ($Integrated) { + $configArgs += '--auth', 'integrated' + } + else { + $token = [System.Net.NetworkCredential]::new($null, $PAT).Password + $configArgs += '--auth', 'pat', '--token', $token + } if ( $LogonCredential ) { $configArgs += '--windowsLogonPassword', ` @@ -336,6 +351,8 @@ function Install-VSTSAgent { Only agents whose names match this filter will be uninstalled. .PARAMETER PAT The personal access token used to auth with VSTS. +.PARAMETER Integrated + Should the agent use integrated auth with VSTS instead of a PAT? #> function Uninstall-VSTSAgent { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "NoVersion")] @@ -357,12 +374,15 @@ function Uninstall-VSTSAgent { [parameter(Mandatory = $false)] [string]$NameFilter, - [parameter(Mandatory = $true)] - [securestring]$PAT + [parameter(Mandatory = $true, ParameterSetName = 'PATAuth')] + [securestring]$PAT, + + [parameter(Mandatory = $true, ParameterSetName = 'IntegratedAuth')] + [switch]$Integrated ) $getArgs = @{} - $PSBoundParameters.Keys | Where-Object { $_ -ne 'PAT' } | ForEach-Object { + $PSBoundParameters.Keys | Where-Object { $_ -ne 'PAT' -and $_ -ne 'Integrated' } | ForEach-Object { $getArgs[$_] = $PSBoundParameters[$_] } @@ -372,7 +392,14 @@ function Uninstall-VSTSAgent { if ( -not $PSCmdlet.ShouldProcess("$($_.Name) - $($_.Path)", "Uninstall")) { return } $configPath = [io.path]::Combine($_.Path.LocalPath, 'config.cmd') - $configArgs = @('remove', '--unattended', '--auth', 'pat', '--token', "$token") + $configArgs = @('remove', '--unattended') + + if ($Integrated) { + $configArgs += '--auth', 'integrated' + } + else { + $configArgs += '--auth', 'pat', '--token', "$token" + } $outFile = [io.path]::Combine($_.Path.LocalPath, "out.log") $errorFile = [io.path]::Combine($_.Path.LocalPath, "error.log")