Skip to content

Commit a56ac3a

Browse files
authored
add proxy support to vsts-task-lib (#268)
1 parent 8f8b3b4 commit a56ac3a

File tree

7 files changed

+172
-3
lines changed

7 files changed

+172
-3
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,7 @@ node/docs/vsotask.json
4141

4242
# tests
4343
node/.taskKey
44+
45+
# powershell compiled helper
46+
powershell/CompiledHelpers/bin
47+
powershell/CompiledHelpers/obj

node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vsts-task-lib",
3-
"version": "2.0.5",
3+
"version": "2.0.6",
44
"description": "VSTS Task SDK",
55
"main": "./task.js",
66
"typings": "./task.d.ts",

node/task.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,43 @@ export function findMatch(defaultRoot: string, patterns: string[] | string, find
15291529
return finalResult;
15301530
}
15311531

1532+
//-----------------------------------------------------
1533+
// Http Proxy Helper
1534+
//-----------------------------------------------------
1535+
1536+
export interface ProxyConfiguration {
1537+
proxyUrl: string;
1538+
proxyUsername?: string;
1539+
proxyPassword?: string;
1540+
proxyBypassHosts?: string[];
1541+
}
1542+
1543+
/**
1544+
* Gets http proxy configuration used by Build/Release agent
1545+
*
1546+
* @return ProxyConfiguration
1547+
*/
1548+
export function getHttpProxyConfiguration(): ProxyConfiguration {
1549+
// min agent version that supports proxy
1550+
assertAgent('2.105.7');
1551+
let proxyUrl: string = getVariable('Agent.ProxyUrl');
1552+
if (proxyUrl && proxyUrl.length > 0) {
1553+
let proxyUsername: string = getVariable('Agent.ProxyUsername');
1554+
let proxyPassword: string = getVariable('Agent.ProxyPassword');
1555+
let proxyBypassHosts: string[] = JSON.parse(getVariable('Agent.ProxyBypassList') || '[]');
1556+
1557+
return {
1558+
proxyUrl: proxyUrl,
1559+
proxyUsername: proxyUsername,
1560+
proxyPassword: proxyPassword,
1561+
proxyBypassHosts: proxyBypassHosts
1562+
};
1563+
}
1564+
else {
1565+
return null;
1566+
}
1567+
}
1568+
15321569
//-----------------------------------------------------
15331570
// Test Publisher
15341571
//-----------------------------------------------------

powershell/CompiledHelpers/VstsTaskSdk.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,94 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Net;
24
using System.Runtime.InteropServices;
5+
using System.Text.RegularExpressions;
36

47
namespace VstsTaskSdk
58
{
69
public class TerminationException : Exception
710
{
811
public TerminationException(String message) : base(message) { }
912
}
13+
14+
public sealed class VstsWebProxy : IWebProxy
15+
{
16+
private string _proxyAddress;
17+
private readonly List<Regex> _regExBypassList = new List<Regex>();
18+
19+
public ICredentials Credentials { get; set; }
20+
21+
public VstsWebProxy(string proxyAddress, string proxyUsername, string proxyPassword, List<string> proxyBypassList)
22+
{
23+
_proxyAddress = proxyAddress?.Trim();
24+
25+
if (string.IsNullOrEmpty(proxyUsername) || string.IsNullOrEmpty(proxyPassword))
26+
{
27+
Credentials = CredentialCache.DefaultNetworkCredentials;
28+
}
29+
else
30+
{
31+
Credentials = new NetworkCredential(proxyUsername, proxyPassword);
32+
}
33+
34+
if (proxyBypassList != null)
35+
{
36+
foreach (string bypass in proxyBypassList)
37+
{
38+
if (string.IsNullOrWhiteSpace(bypass))
39+
{
40+
continue;
41+
}
42+
else
43+
{
44+
try
45+
{
46+
Regex bypassRegex = new Regex(bypass.Trim(), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.ECMAScript);
47+
_regExBypassList.Add(bypassRegex);
48+
}
49+
catch (Exception)
50+
{
51+
// eat all exceptions
52+
}
53+
}
54+
}
55+
}
56+
}
57+
58+
public Uri GetProxy(Uri destination)
59+
{
60+
if (IsBypassed(destination))
61+
{
62+
return destination;
63+
}
64+
else
65+
{
66+
return new Uri(_proxyAddress);
67+
}
68+
}
69+
70+
public bool IsBypassed(Uri uri)
71+
{
72+
return string.IsNullOrEmpty(_proxyAddress) || uri.IsLoopback || IsMatchInBypassList(uri);
73+
}
74+
75+
private bool IsMatchInBypassList(Uri input)
76+
{
77+
string matchUriString = input.IsDefaultPort ?
78+
input.Scheme + "://" + input.Host :
79+
input.Scheme + "://" + input.Host + ":" + input.Port.ToString();
80+
81+
foreach (Regex r in _regExBypassList)
82+
{
83+
if (r.IsMatch(matchUriString))
84+
{
85+
return true;
86+
}
87+
}
88+
89+
return false;
90+
}
91+
}
1092
}
1193

1294
namespace VstsTaskSdk.FS

powershell/VstsTaskSdk/ServerOMFunctions.ps1

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ If not specified, defaults to the directory of the entry script for the task.
324324
# .PARAMETER VssCredentials
325325
# Credentials to use when intializing the HTTP client. If not specified, the default uses the agent job token to construct the credentials object. The identity associated with the token depends on the scope selected in the build/release definition (either the project collection build/release service identity, or the project build/release service identity).
326326
327+
# .PARAMETER WebProxy
328+
# WebProxy to use when intializing the HTTP client. If not specified, the default uses the proxy configuration agent current has.
329+
327330
.EXAMPLE
328331
$projectHttpClient = Get-VstsVssHttpClient -TypeName Microsoft.TeamFoundation.Core.WebApi.ProjectHttpClient
329332
$projectHttpClient.GetProjects().Result
@@ -338,7 +341,9 @@ function Get-VssHttpClient {
338341

339342
[string]$Uri,
340343

341-
$VssCredentials)
344+
$VssCredentials,
345+
346+
$WebProxy = (Get-WebProxy))
342347

343348
Trace-EnteringInvocation -InvocationInfo $MyInvocation
344349
$originalErrorActionPreference = $ErrorActionPreference
@@ -361,6 +366,9 @@ function Get-VssHttpClient {
361366
# Validate the type can be loaded.
362367
$null = Get-OMType -TypeName $TypeName -OMKind 'WebApi' -OMDirectory $OMDirectory -Require
363368

369+
# Update proxy setting for vss http client
370+
[Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler]::DefaultWebProxy = $WebProxy
371+
364372
# Try to construct the HTTP client.
365373
Write-Verbose "Constructing HTTP client."
366374
try {
@@ -421,6 +429,42 @@ function Get-VssHttpClient {
421429
}
422430
}
423431

432+
<#
433+
.SYNOPSIS
434+
Gets a VstsTaskSdk.VstsWebProxy
435+
436+
.DESCRIPTION
437+
Gets an instance of a VstsTaskSdk.VstsWebProxy that has same proxy configuration as Build/Release agent.
438+
439+
VstsTaskSdk.VstsWebProxy implement System.Net.IWebProxy interface.
440+
441+
.EXAMPLE
442+
$webProxy = Get-VstsWebProxy
443+
$webProxy.GetProxy(New-Object System.Uri("https://github.com/Microsoft/vsts-task-lib"))
444+
#>
445+
function Get-WebProxy {
446+
[CmdletBinding()]
447+
param()
448+
449+
Trace-EnteringInvocation -InvocationInfo $MyInvocation
450+
try
451+
{
452+
# Min agent version that supports proxy
453+
Assert-Agent -Minimum '2.105.7'
454+
455+
$proxyUrl = Get-TaskVariable -Name Agent.ProxyUrl
456+
$proxyUserName = Get-TaskVariable -Name Agent.ProxyUserName
457+
$proxyPassword = Get-TaskVariable -Name Agent.ProxyPassword
458+
$proxyBypassListJson = Get-TaskVariable -Name Agent.ProxyBypassList
459+
[string[]]$ProxyBypassList = ConvertFrom-Json -InputObject $ProxyBypassListJson
460+
461+
return New-Object -TypeName VstsTaskSdk.VstsWebProxy -ArgumentList @($proxyUrl, $proxyUserName, $proxyPassword, $proxyBypassList)
462+
}
463+
finally {
464+
Trace-LeavingInvocation -InvocationInfo $MyInvocation
465+
}
466+
}
467+
424468
########################################
425469
# Private functions.
426470
########################################

powershell/VstsTaskSdk/VstsTaskSdk.psm1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ Export-ModuleMember -Function @(
7979
'Trace-EnteringInvocation'
8080
'Trace-LeavingInvocation'
8181
'Trace-Path'
82+
# Proxy functions
83+
'Get-WebProxy'
8284
)
8385

8486
# Override Out-Default globally.

powershell/make.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ target.build = function() {
2828
var minimatchPackage = util.downloadArchive('https://www.nuget.org/api/v2/package/minimatch/1.1.0');
2929
util.cp(path.join(minimatchPackage, 'lib', 'portable-net40%2Bsl50%2Bwin%2Bwp80', 'Minimatch.dll'), path.join(buildPath, 'VstsTaskSdk'));
3030

31-
var compiledHelperPackage = util.downloadArchive('https://vstsagenttools.blob.core.windows.net/tools/VstsTaskSdkCompiledHelpers/VstsTaskSdk.zip');
31+
var compiledHelperPackage = util.downloadArchive('https://vstsagenttools.blob.core.windows.net/tools/VstsTaskSdkCompiledHelpers/2/VstsTaskSdk.zip');
3232
util.cp(path.join(compiledHelperPackage, 'VstsTaskSdk.dll'), path.join(buildPath, 'VstsTaskSdk'));
3333

3434
// stamp the version number from the package.json onto the PowerShell module definition

0 commit comments

Comments
 (0)