Skip to content

Commit a710e74

Browse files
authored
Implement AzModule for secrets detection in autorest (#24411)
1 parent 1432bd2 commit a710e74

File tree

6 files changed

+53
-8
lines changed

6 files changed

+53
-8
lines changed

src/Accounts/Accounts/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-->
2020

2121
## Upcoming Release
22+
* Implemented secrets detection feature for autorest modules.
2223
* Added `AsSecureString` to `Get-AzAccessToken` to convert the returned token to SecureString [#24190].
2324
* Upgraded Azure.Core to 1.37.0.
2425

src/Accounts/Accounts/CommonModule/AzModule.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.Rest.Azure;
1919
using Microsoft.Rest.Serialization;
2020
using Microsoft.WindowsAzure.Commands.Common;
21+
using Microsoft.WindowsAzure.Commands.Common.Sanitizer;
2122
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2223
using Newtonsoft.Json;
2324
using System;
@@ -31,7 +32,6 @@
3132

3233
namespace Microsoft.Azure.Commands.Common
3334
{
34-
3535
using GetEventData = Func<EventArgs>;
3636
using PipelineChangeDelegate = Action<Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Task<HttpResponseMessage>>, Task<HttpResponseMessage>>>;
3737
using SignalDelegate = Func<string, CancellationToken, Func<EventArgs>, Task>;
@@ -66,7 +66,6 @@ static AzModule()
6666
DeserializationSettings.Converters.Add(new CloudErrorJsonConverter());
6767
}
6868

69-
7069
public AzModule(ICommandRuntime runtime, IEventStore eventHandler)
7170
{
7271
_runtime = runtime;
@@ -84,11 +83,10 @@ public AzModule(ICommandRuntime runtime, IEventStore store, TelemetryProvider pr
8483
{
8584
_deferredEvents = store;
8685
_runtime = runtime;
87-
_logger = new AdalLogger(_deferredEvents.GetDebugLogger()); ;
86+
_logger = new AdalLogger(_deferredEvents.GetDebugLogger());
8887
_telemetry = provider;
8988
}
9089

91-
9290
/// <summary>
9391
/// Called when the module is loading. Allows adding HTTP pipeline steps that will always be present.
9492
/// </summary>
@@ -366,6 +364,40 @@ await signal(Events.Debug, cancellationToken,
366364
}
367365
}
368366

367+
public void SanitizerHandler(object sanitizingObject, string telemetryId)
368+
{
369+
if (AzureSession.Instance.TryGetComponent<IOutputSanitizer>(nameof(IOutputSanitizer), out var outputSanitizer))
370+
{
371+
if (outputSanitizer?.RequireSecretsDetection == true)
372+
{
373+
outputSanitizer.Sanitize(sanitizingObject, out var telemetry);
374+
if (_telemetry.TryGetValue(telemetryId, out var qos))
375+
{
376+
qos?.SanitizerInfo?.Combine(telemetry);
377+
}
378+
}
379+
}
380+
}
381+
382+
public Dictionary<string, string> GetTelemetryInfo(string telemetryId)
383+
{
384+
Dictionary<string, string> telemetryInfo = null;
385+
if (_telemetry.TryGetValue(telemetryId, out var qos))
386+
{
387+
if (qos?.SanitizerInfo?.DetectedProperties?.Count > 0)
388+
{
389+
var sanitizedProperties = string.Join(", ", qos.SanitizerInfo.DetectedProperties);
390+
var invocationName = qos.InvocationName;
391+
telemetryInfo = new Dictionary<string, string>
392+
{
393+
{ "SanitizedProperties", sanitizedProperties },
394+
{ "InvocationName", invocationName }
395+
};
396+
}
397+
}
398+
399+
return telemetryInfo;
400+
}
369401

370402
/// <summary>
371403
/// Free resources associated with this instance
@@ -393,7 +425,6 @@ public virtual void Dispose(bool disposing)
393425
}
394426
}
395427

396-
397428
private async void DrainDeferredEvents(SignalDelegate signal, CancellationToken token)
398429
{
399430
EventData data;
@@ -403,5 +434,4 @@ private async void DrainDeferredEvents(SignalDelegate signal, CancellationToken
403434
}
404435
}
405436
}
406-
407437
}

src/Accounts/Accounts/CommonModule/RegisterAzModule.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ protected override void ProcessRecord()
5858
// this gets called at module load time (allows you to change the http pipeline)
5959
OnModuleLoad = module.OnModuleLoad,
6060

61+
// this gets called to sanitize the output object
62+
SanitizerHandler = module.SanitizerHandler,
63+
64+
// this gets called to get the sanitizer info
65+
GetTelemetryInfo = module.GetTelemetryInfo,
66+
6167
// this gets called before the generated cmdlet makes a call across the wire (allows you to change the HTTP pipeline)
6268
OnNewRequest = ContextAdapter.Instance.OnNewRequest,
6369

src/Accounts/Accounts/CommonModule/TelemetryProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.Azure.Commands.Profile.CommonModule;
2020
using Microsoft.Azure.Commands.Profile.Properties;
2121
using Microsoft.WindowsAzure.Commands.Common;
22+
using Microsoft.WindowsAzure.Commands.Common.Sanitizer;
2223
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2324
using System;
2425
using System.Collections;
@@ -155,6 +156,7 @@ public virtual AzurePSQoSEvent CreateQosEvent(InvocationInfo invocationInfo, str
155156
PSVersion = AzurePSCmdlet.PowerShellVersion,
156157
HostVersion = AzurePSCmdlet.PSHostVersion,
157158
PSHostName = AzurePSCmdlet.PSHostName,
159+
SanitizerInfo = new SanitizerTelemetry()
158160
};
159161

160162
if (invocationInfo != null)

src/Accounts/Accounts/CommonModule/VTable.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ namespace Microsoft.Azure.Commands.Common
3333
global::System.Action<global::System.Func<global::System.Net.Http.HttpRequestMessage, global::System.Threading.CancellationToken, global::System.Action, global::System.Func<string, global::System.Threading.CancellationToken, global::System.Func<global::System.EventArgs>, global::System.Threading.Tasks.Task>, global::System.Func<global::System.Net.Http.HttpRequestMessage, global::System.Threading.CancellationToken, global::System.Action, global::System.Func<string, global::System.Threading.CancellationToken, global::System.Func<global::System.EventArgs>, global::System.Threading.Tasks.Task>, global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage>>, global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage>>>,
3434
global::System.Func<string, string, string, string, global::System.Uri, string>,
3535
System.Collections.Generic.IDictionary<string, object>>;
36+
using SanitizerDelegate = Action<object, string>;
37+
using GetTelemetryInfoDelegate = Func<string, System.Collections.Generic.Dictionary<string, string>>;
3638

3739
/// <summary>
3840
/// The Virtual Call table of the functions to be exported to the generated module
@@ -58,7 +60,6 @@ public class VTable
5860

5961
public TelemetryDelegate Telemetry;
6062

61-
6263
/// <summary>
6364
/// The cmdlet will call this for every event during the pipeline.
6465
/// </summary>
@@ -104,6 +105,10 @@ public class VTable
104105

105106
public AuthorizeRequestDelegate AddAuthorizeRequestHandler;
106107

108+
public SanitizerDelegate SanitizerHandler;
109+
110+
public GetTelemetryInfoDelegate GetTelemetryInfo;
111+
107112
/// <summary>
108113
/// Called for well-known parameters that require argument completers, it
109114
/// </summary>

src/Accounts/Authentication/Sanitizer/Providers/SanitizerProperty.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public class SanitizerProperty
2929

3030
public SanitizerProperty(PropertyInfo property)
3131
{
32-
PropertyName = property.Name;
32+
var fullPropName = property.Name;
33+
PropertyName = fullPropName.Contains(".") ? fullPropName.Substring(fullPropName.LastIndexOf('.') + 1) : fullPropName;
3334
PropertyType = property.PropertyType;
3435
ValueSupplier = property;
3536
}

0 commit comments

Comments
 (0)