Skip to content

Commit 69bb3fc

Browse files
ssteinerStephan Steiner
andauthored
Add proxy support (#172)
* implemented proxy support for BlobStorageTarget * using booleans instead of Layout for `UseProxy` and `UseDefaultCredentialsForProxy` leave `BlobClientOptions` null unless proxy support is enabled * Using `NoProxy` to disable the use of any proxies only creating a custom `Transport` for `BlobClientOptions` if it is warranted (custom proxy/proxy credentials, disabling proxy or using default credentials for proxy) * Using `ProxyType` to control what kind of proxy we get instead, replacing `NoProxy` * only create a BlobClientInstance for a custom proxy configuration * CreateProxy is now only used to really create a custom proxy made RequiresManualProxyConfiguration even more precise * moved `HttpPipelineTransport` creation `ProxyHelper` * moved `HttpClientTransport` creation to ProxyHelpers * using NoProxy to control whether proxy bypass is enabled removed ProxyType * implemented proxy support for AzureDataTables, AzureEventGrid and AzureQueueStorage targets * fixed XML comment for NoProxy (wrongly referenced ProxyPassword instead of ProxyAddress) simplified XML comment for UseDefaultCredentialsForProxy (removed statement about NoProxy) --------- Co-authored-by: Stephan Steiner <[email protected]>
1 parent 352dc44 commit 69bb3fc

File tree

21 files changed

+370
-38
lines changed

21 files changed

+370
-38
lines changed

src/NLog.Extensions.AzureBlobStorage/BlobStorageTarget.cs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Net.Http;
34
using System.Text;
45
using System.Threading;
56
using System.Threading.Tasks;
7+
using Azure.Core.Pipeline;
68
using Azure.Storage.Blobs;
79
using Azure.Storage.Blobs.Specialized;
810
using NLog.Common;
911
using NLog.Config;
12+
using NLog.Extensions.AzureBlobStorage;
1013
using NLog.Extensions.AzureStorage;
1114
using NLog.Layouts;
1215

@@ -105,6 +108,32 @@ public sealed class BlobStorageTarget : AsyncTaskTarget
105108
/// </summary>
106109
public Layout ClientAuthSecret { get; set; }
107110

111+
/// <summary>
112+
/// Bypasses any system proxy and proxy in <see cref="ProxyAddress"/> when set to <see langword="true"/>.
113+
/// Overrides <see cref="ProxyAddress"/>.
114+
/// </summary>
115+
public bool NoProxy { get; set; }
116+
117+
/// <summary>
118+
/// Address of the proxy server to use (e.g. http://proxyserver:8080).
119+
/// </summary>
120+
public Layout ProxyAddress { get; set; }
121+
122+
/// <summary>
123+
/// Login to use for the proxy server. Requires <see cref="ProxyPassword"/>.
124+
/// </summary>
125+
public Layout ProxyLogin { get; set; }
126+
127+
/// <summary>
128+
/// Password to use for the proxy server. Requires <see cref="ProxyLogin"/>.
129+
/// </summary>
130+
public Layout ProxyPassword { get; set; }
131+
132+
/// <summary>
133+
/// Uses the default credentials (<see cref="System.Net.CredentialCache.DefaultCredentials"/>) for the proxy server, overriding any values that may have been set in <see cref="ProxyLogin"/> and <see cref="ProxyPassword"/>.
134+
/// </summary>
135+
public bool UseDefaultCredentialsForProxy { get; set; }
136+
108137
/// <summary>
109138
/// Name of the Blob storage Container
110139
/// </summary>
@@ -184,6 +213,7 @@ protected override void InitializeTarget()
184213

185214
Dictionary<string, string> blobMetadata = null;
186215
Dictionary<string, string> blobTags = null;
216+
ProxySettings proxySettings = null;
187217

188218
var defaultLogEvent = LogEventInfo.CreateNullEvent();
189219

@@ -202,6 +232,14 @@ protected override void InitializeTarget()
202232
clientAuthId = ClientAuthId?.Render(defaultLogEvent);
203233
clientAuthSecret = ClientAuthSecret?.Render(defaultLogEvent);
204234
}
235+
proxySettings = new ProxySettings
236+
{
237+
NoProxy = NoProxy,
238+
UseDefaultCredentials = UseDefaultCredentialsForProxy,
239+
Address = ProxyAddress?.Render(defaultLogEvent),
240+
Login = ProxyLogin?.Render(defaultLogEvent),
241+
Password = ProxyPassword?.Render(defaultLogEvent)
242+
};
205243

206244
if (BlobMetadata?.Count > 0)
207245
{
@@ -232,7 +270,7 @@ protected override void InitializeTarget()
232270
}
233271
}
234272

235-
_cloudBlobService.Connect(connectionString, serviceUri, tenantIdentity, managedIdentityResourceId, managedIdentityClientId, sharedAccessSignature, storageAccountName, storageAccountAccessKey, clientAuthId, clientAuthSecret, blobMetadata, blobTags);
273+
_cloudBlobService.Connect(connectionString, serviceUri, tenantIdentity, managedIdentityResourceId, managedIdentityClientId, sharedAccessSignature, storageAccountName, storageAccountAccessKey, clientAuthId, clientAuthSecret, blobMetadata, blobTags, proxySettings);
236274
InternalLogger.Debug("AzureBlobStorageTarget(Name={0}): Initialized", Name);
237275
}
238276
catch (Exception ex)
@@ -445,33 +483,46 @@ class CloudBlobService : ICloudBlobService
445483
private AppendBlobClient _appendBlob;
446484
private BlobContainerClient _container;
447485

448-
public void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, IDictionary<string, string> blobMetadata, IDictionary<string, string> blobTags)
486+
public void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, IDictionary<string, string> blobMetadata, IDictionary<string, string> blobTags, ProxySettings proxySettings = null)
449487
{
450488
_blobMetadata = blobMetadata?.Count > 0 ? blobMetadata : null;
451489
_blobTags = blobTags?.Count > 0 ? blobTags : null;
452-
490+
BlobClientOptions options = ConfigureClientOptions(proxySettings);
453491
if (string.IsNullOrWhiteSpace(serviceUri))
454492
{
455-
_client = new BlobServiceClient(connectionString);
493+
_client = new BlobServiceClient(connectionString, options);
456494
}
457495
else if (!string.IsNullOrEmpty(sharedAccessSignature))
458496
{
459-
_client = new BlobServiceClient(new Uri(serviceUri), new Azure.AzureSasCredential(sharedAccessSignature));
497+
_client = new BlobServiceClient(new Uri(serviceUri), new Azure.AzureSasCredential(sharedAccessSignature), options);
460498
}
461499
else if (!string.IsNullOrWhiteSpace(storageAccountName))
462500
{
463-
_client = new BlobServiceClient(new Uri(serviceUri), new Azure.Storage.StorageSharedKeyCredential(storageAccountName, storageAccountAccessKey));
501+
_client = new BlobServiceClient(new Uri(serviceUri), new Azure.Storage.StorageSharedKeyCredential(storageAccountName, storageAccountAccessKey), options);
464502
}
465503
else if (!string.IsNullOrEmpty(clientAuthId) && !string.IsNullOrEmpty(clientAuthSecret) && !string.IsNullOrEmpty(tenantIdentity))
466504
{
467505
var tokenCredentials = new Azure.Identity.ClientSecretCredential(tenantIdentity, clientAuthId, clientAuthSecret);
468-
_client = new BlobServiceClient(new Uri(serviceUri), tokenCredentials);
506+
_client = new BlobServiceClient(new Uri(serviceUri), tokenCredentials, options);
469507
}
470508
else
471509
{
472510
var tokenCredentials = AzureCredentialHelpers.CreateTokenCredentials(managedIdentityClientId, tenantIdentity, managedIdentityResourceId);
473-
_client = new BlobServiceClient(new Uri(serviceUri), tokenCredentials);
511+
_client = new BlobServiceClient(new Uri(serviceUri), tokenCredentials, options);
512+
}
513+
}
514+
515+
private static BlobClientOptions ConfigureClientOptions(ProxySettings proxySettings)
516+
{
517+
var transport = proxySettings?.CreateHttpClientTransport();
518+
if (transport != null)
519+
{
520+
return new BlobClientOptions
521+
{
522+
Transport = transport
523+
};
474524
}
525+
return null;
475526
}
476527

477528
public Task AppendFromByteArrayAsync(string containerName, string blobName, string contentType, byte[] buffer, CancellationToken cancellationToken)
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
using System.Collections.Generic;
1+
using NLog.Extensions.AzureBlobStorage;
2+
using System.Collections.Generic;
23
using System.Threading;
34
using System.Threading.Tasks;
45

56
namespace NLog.Extensions.AzureStorage
67
{
78
interface ICloudBlobService
89
{
9-
void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, IDictionary<string, string> blobMetadata, IDictionary<string, string> blobTags);
10+
void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, IDictionary<string, string> blobMetadata, IDictionary<string, string> blobTags, ProxySettings proxySettings = null);
1011
Task AppendFromByteArrayAsync(string containerName, string blobName, string contentType, byte[] buffer, CancellationToken cancellationToken);
1112
}
1213
}

src/NLog.Extensions.AzureBlobStorage/NLog.Extensions.AzureBlobStorage.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Docs: https://github.com/JDetmar/NLog.Extensions.AzureStorage/blob/master/src/NL
4040
<ItemGroup>
4141
<Compile Include="..\NLog.Extensions.AzureStorage\AzureCredentialHelper.cs" Link="AzureCredentialHelper.cs" />
4242
<Compile Include="..\NLog.Extensions.AzureStorage\AzureStorageNameCache.cs" Link="AzureStorageNameCache.cs" />
43+
<Compile Include="..\NLog.Extensions.AzureStorage\ProxyHelpers.cs" Link="ProxyHelpers.cs" />
4344
<Compile Include="..\NLog.Extensions.AzureStorage\SortHelpers.cs" Link="SortHelpers.cs" />
4445
</ItemGroup>
4546

src/NLog.Extensions.AzureBlobStorage/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ _clientAuthId_ - clientId for `ClientSecretCredential` authentication. Requires
5757

5858
_clientAuthSecret_ - clientSecret for `ClientSecretCredential` authentication. Requires `serviceUri`,`tenantIdentity` and `clientAuthId`.
5959

60+
_noProxy_ - Bypasses any system proxy and proxy in `ProxyAddress` when set to `true`.
61+
62+
_proxyAddress_ - Address of the proxy server to use (e.g. http://proxyserver:8080).
63+
64+
_proxyLogin_ - Login to use for the proxy server. Requires `proxyPassword`.
65+
66+
_proxyPassword_ - Password to use for the proxy server. Requires `proxyLogin`.
67+
68+
_useDefaultCredentialsForProxy_ - Uses the default credentials (`System.Net.CredentialCache.DefaultCredentials`) for the proxy server, overriding any values that may have been set in `proxyLogin` and `proxyPassword`.
69+
6070
### Batching Policy
6171

6272
_batchSize_ - Number of EventData items to send in a single batch (Default=100)

src/NLog.Extensions.AzureDataTables/DataTablesTarget.cs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Azure.Data.Tables;
77
using NLog.Common;
88
using NLog.Config;
9+
using NLog.Extensions.AzureBlobStorage;
910
using NLog.Extensions.AzureStorage;
1011
using NLog.Layouts;
1112

@@ -144,6 +145,33 @@ public override int GetHashCode()
144145
/// </summary>
145146
public Layout ClientAuthSecret { get; set; }
146147

148+
/// <summary>
149+
/// Bypasses any system proxy and proxy in <see cref="ProxyAddress"/> when set to <see langword="true"/>.
150+
/// Overrides <see cref="ProxyAddress"/>.
151+
/// </summary>
152+
public bool NoProxy { get; set; }
153+
154+
/// <summary>
155+
/// Address of the proxy server to use (e.g. http://proxyserver:8080).
156+
/// </summary>
157+
public Layout ProxyAddress { get; set; }
158+
159+
/// <summary>
160+
/// Login to use for the proxy server. Requires <see cref="ProxyPassword"/>.
161+
/// </summary>
162+
public Layout ProxyLogin { get; set; }
163+
164+
/// <summary>
165+
/// Password to use for the proxy server. Requires <see cref="ProxyLogin"/>.
166+
/// </summary>
167+
public Layout ProxyPassword { get; set; }
168+
169+
/// <summary>
170+
/// Uses the default credentials (<see cref="System.Net.CredentialCache.DefaultCredentials"/>) for the proxy server, overriding any values that may have been set in <see cref="ProxyLogin"/> and <see cref="ProxyPassword"/>.
171+
/// </summary>
172+
public bool UseDefaultCredentialsForProxy { get; set; }
173+
174+
147175
/// <summary>
148176
/// Gets or sets the name of the Azure table where log entries will be stored.
149177
/// </summary>
@@ -209,6 +237,8 @@ protected override void InitializeTarget()
209237
string clientAuthId = string.Empty;
210238
string clientAuthSecret = string.Empty;
211239

240+
ProxySettings proxySettings = null;
241+
212242
var defaultLogEvent = LogEventInfo.CreateNullEvent();
213243

214244
try
@@ -226,8 +256,16 @@ protected override void InitializeTarget()
226256
clientAuthId = ClientAuthId?.Render(defaultLogEvent);
227257
clientAuthSecret = ClientAuthSecret?.Render(defaultLogEvent);
228258
}
229-
230-
_cloudTableService.Connect(connectionString, serviceUri, tenantIdentity, managedIdentityResourceId, managedIdentityClientId, sharedAccessSignature, accountName, accessKey, clientAuthId, clientAuthSecret);
259+
proxySettings = new ProxySettings
260+
{
261+
NoProxy = NoProxy,
262+
UseDefaultCredentials = UseDefaultCredentialsForProxy,
263+
Address = ProxyAddress?.Render(defaultLogEvent),
264+
Login = ProxyLogin?.Render(defaultLogEvent),
265+
Password = ProxyPassword?.Render(defaultLogEvent)
266+
};
267+
268+
_cloudTableService.Connect(connectionString, serviceUri, tenantIdentity, managedIdentityResourceId, managedIdentityClientId, sharedAccessSignature, accountName, accessKey, clientAuthId, clientAuthSecret, proxySettings);
231269
InternalLogger.Debug("AzureDataTablesTarget(Name={0}): Initialized", Name);
232270
}
233271
catch (Exception ex)
@@ -452,19 +490,20 @@ class CloudTableService : ICloudTableService
452490
private TableServiceClient _client;
453491
private TableClient _table;
454492

455-
public void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret)
493+
public void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, ProxySettings proxySettings = null)
456494
{
495+
TableClientOptions options = ConfigureClientOptions(proxySettings);
457496
if (string.IsNullOrWhiteSpace(serviceUri))
458497
{
459-
_client = new TableServiceClient(connectionString);
498+
_client = new TableServiceClient(connectionString, options);
460499
}
461500
else if (!string.IsNullOrWhiteSpace(sharedAccessSignature))
462501
{
463-
_client = new TableServiceClient(new Uri(serviceUri), new Azure.AzureSasCredential(sharedAccessSignature));
502+
_client = new TableServiceClient(new Uri(serviceUri), new Azure.AzureSasCredential(sharedAccessSignature), options);
464503
}
465504
else if (!string.IsNullOrWhiteSpace(storageAccountName))
466505
{
467-
_client = new TableServiceClient(new Uri(serviceUri), new TableSharedKeyCredential(storageAccountName, storageAccountAccessKey));
506+
_client = new TableServiceClient(new Uri(serviceUri), new TableSharedKeyCredential(storageAccountName, storageAccountAccessKey), options);
468507
}
469508
else if (!string.IsNullOrEmpty(clientAuthId) && !string.IsNullOrEmpty(clientAuthSecret) && !string.IsNullOrEmpty(tenantIdentity))
470509
{
@@ -474,10 +513,23 @@ public void Connect(string connectionString, string serviceUri, string tenantIde
474513
else
475514
{
476515
var tokenCredentials = AzureCredentialHelpers.CreateTokenCredentials(managedIdentityClientId, tenantIdentity, managedIdentityResourceId);
477-
_client = new TableServiceClient(new Uri(serviceUri), tokenCredentials);
516+
_client = new TableServiceClient(new Uri(serviceUri), tokenCredentials, options);
478517
}
479518
}
480519

520+
private static TableClientOptions ConfigureClientOptions(ProxySettings proxySettings)
521+
{
522+
var transport = proxySettings?.CreateHttpClientTransport();
523+
if (transport != null)
524+
{
525+
return new TableClientOptions
526+
{
527+
Transport = transport
528+
};
529+
}
530+
return null;
531+
}
532+
481533
public Task SubmitTransactionAsync(string tableName, IEnumerable<TableTransactionAction> tableTransaction, CancellationToken cancellationToken)
482534
{
483535
var table = _table;

src/NLog.Extensions.AzureDataTables/ICloudTableService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
using System.Threading;
33
using System.Threading.Tasks;
44
using Azure.Data.Tables;
5+
using NLog.Extensions.AzureBlobStorage;
56

67
namespace NLog.Extensions.AzureStorage
78
{
89
interface ICloudTableService
910
{
10-
void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret);
11+
void Connect(string connectionString, string serviceUri, string tenantIdentity, string managedIdentityResourceId, string managedIdentityClientId, string sharedAccessSignature, string storageAccountName, string storageAccountAccessKey, string clientAuthId, string clientAuthSecret, ProxySettings proxySettings = null);
1112
Task SubmitTransactionAsync(string tableName, IEnumerable<TableTransactionAction> tableTransaction, CancellationToken cancellationToken);
1213
}
1314
}

src/NLog.Extensions.AzureDataTables/NLog.Extensions.AzureDataTables.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Docs: https://github.com/JDetmar/NLog.Extensions.AzureStorage/blob/master/src/NL
4040
<ItemGroup>
4141
<Compile Include="..\NLog.Extensions.AzureStorage\AzureCredentialHelper.cs" Link="AzureCredentialHelper.cs" />
4242
<Compile Include="..\NLog.Extensions.AzureStorage\AzureStorageNameCache.cs" Link="AzureStorageNameCache.cs" />
43+
<Compile Include="..\NLog.Extensions.AzureStorage\ProxyHelpers.cs" Link="ProxyHelpers.cs" />
4344
<Compile Include="..\NLog.Extensions.AzureStorage\SortHelpers.cs" Link="SortHelpers.cs" />
4445
</ItemGroup>
4546

src/NLog.Extensions.AzureDataTables/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ _clientAuthId_ - clientId for `ClientSecretCredential` authentication. Requires
4848

4949
_clientAuthSecret_ - clientSecret for `ClientSecretCredential` authentication. Requires `serviceUri`,`tenantIdentity` and `clientAuthId`.
5050

51+
_noProxy_ - Bypasses any system proxy and proxy in `ProxyAddress` when set to `true`.
52+
53+
_proxyAddress_ - Address of the proxy server to use (e.g. http://proxyserver:8080).
54+
55+
_proxyLogin_ - Login to use for the proxy server. Requires `proxyPassword`.
56+
57+
_proxyPassword_ - Password to use for the proxy server. Requires `proxyLogin`.
58+
59+
_useDefaultCredentialsForProxy_ - Uses the default credentials (`System.Net.CredentialCache.DefaultCredentials`) for the proxy server, overriding any values that may have been set in `proxyLogin` and `proxyPassword`.
60+
5161
_tableName_ - Azure table name. [Layout](https://github.com/NLog/NLog/wiki/Layouts)
5262

5363
_rowKey_ - Azure Table RowKey. [Layout](https://github.com/NLog/NLog/wiki/Layouts). Default = "InverseTicks_${guid}"

0 commit comments

Comments
 (0)