Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AAD: Handling Azure.Core.TokenCredential #2191

Merged
merged 64 commits into from
May 27, 2021
Merged

Conversation

TimothyMothra
Copy link
Member

@TimothyMothra TimothyMothra commented Mar 25, 2021

Adding support for Azure.Core.TokenCredential to the TelemetryConfiguration

For more information see the parent item: #2190.

Introduction

We have a unique challenge of needing to support Azure.Core.TokenCredential while having incompatible Frameworks.

image

To address this I'm making the assumption that if a customer's application is able to create an instance of TokenCredential, then they also have the Azure.Core assembly in their runtime.
Going off of this assumption, we're able to use reflection to access the methods of TokenCredential and return types available in Azure.Core.
This approach is validated in unit tests.

Implementation

TelemetryConfiguration.SetCredential

We need a way for a customer to provide an implementation of Azure.Core.TokenCredential.
For this, I've introduced a new method TelemetryConfiguration.SetCredential.

/// <summary>
/// Set a TokenCredential for this configuration.
/// </summary>
/// <param name="tokenCredential">An instance of Azure.Core.TokenCredential.</param>
public void SetCredential(object tokenCredential) => this.CredentialEnvelope = new ReflectionCredentialEnvelope(tokenCredential);

We accept Object and validate that the provided object inherits TokenCredential.
We store this in the new property TelemetryConfiguration.CredentialEnvelope which is accessible by all internal classes in the SDK.

CredentialEnvelope

We hold the instance of TokenCredential in a new class ReflectionCredentialEnvelope which as the name suggests, uses Reflection to interact with the Object that was provided.

/// <summary>
/// Create an instance of <see cref="ReflectionCredentialEnvelope"/>.
/// </summary>
/// <param name="tokenCredential">An instance of Azure.Core.TokenCredential.</param>
public ReflectionCredentialEnvelope(object tokenCredential)
{
this.tokenCredential = tokenCredential ?? throw new ArgumentNullException(nameof(tokenCredential));
if (tokenCredential.GetType().IsSubclassOf(Type.GetType("Azure.Core.TokenCredential, Azure.Core")))
{
this.tokenRequestContext = AzureCore.MakeTokenRequestContext(scopes: CredentialConstants.GetScopes());
}
else
{
throw new ArgumentException($"The provided {nameof(tokenCredential)} must inherit Azure.Core.TokenCredential", nameof(tokenCredential));
}
}

@TimothyMothra TimothyMothra self-assigned this Mar 25, 2021
@reyang reyang requested a review from ThomsonTan March 25, 2021 03:33
@pharring

This comment has been minimized.

/// <summary>
/// Gets an envelope for Azure.Core.TokenCredential which provides an AAD Authenticated token.
/// </summary>
public CredentialEnvelope CredentialEnvelope { get; private set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this internal, if end users are not expected to read this back.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pharring, We're planning on making the CredentialEnvelope internal.
We want to get your library added to our InternalsVisibleTo here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiaomi7732 for https://github.com/microsoft/ApplicationInsights-Profiler-AspNetCore

Snapshot Collector is Microsoft.ApplicationInsights.SnapshotCollector, but note that it has a different public key.

Copy link
Member

@xiaomi7732 xiaomi7732 May 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tagging me on this. AI.SDK and Profiler have different build cycles - and we have mixed references. How are we going to make that work?

For example, our desktop build (no StrongName) assemblies might reference public/stable version of app insights SDK, in which case, the InternvalVisibileTo (to a strongNamed assembly) won't work. What is that I missed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to worry about version numbers. InternalsVisibleTo uses just the assembly's name and public key. The question really is whether you expect to take a dependency on a version of the core SDK that has CredentialEnvelope, or would you stick with an older version and use reflection to get CredentialEnvelope.

I still haven't decided for Snapshot Collector. There's going to be some reflection anyway in order to use the CredentialEnvelope.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this topic, I think I am asked to provide assembly names and public keys so that in Core SDK, it knows to expose the internal classes.

The deal is, during the development, our assemblies aren't going to be strongnamed - that means we won't be able to see the internal classes in the Core SDK anyway.

On the other hand, reflection will work, with or without InternalVisibleTo.

So, what is the point to add the InternalVisibleTo for our assemblies? And that is what I am asking, in case I missed something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're changing this property to internal.
Optionally, if you want to utilize this without reflection you can submit a PR to add your SDK to our InternalsVisibleTo.

@TimothyMothra TimothyMothra changed the title [POC] AAD: Handling TokenCredential AAD: Handling Azure.Core.TokenCredential May 26, 2021
@TimothyMothra TimothyMothra marked this pull request as ready for review May 26, 2021 18:23
SdkInternalOperationsMonitor.Enter();
try
{
return await AzureCore.InvokeGetTokenAsync(this.tokenCredential, this.tokenRequestContext, cancellationToken).ConfigureAwait(true);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cijothomas , Is ConfigureAwait(true) the correct usage for SdkInternalOperationsMonitor ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I answered my own question.
ProfileServiceWrapper calls Async methods inside an InternalOperation.

private async Task<string> SendRequestAsync(string instrumentationKey)
{
try
{
SdkInternalOperationsMonitor.Enter();
var resultMessage = await this.GetAsync(instrumentationKey).ConfigureAwait(false);
if (resultMessage.IsSuccessStatusCode)
{
return await resultMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
}
else
{
this.FailedRequestsManager.RegisterFetchFailure(instrumentationKey, resultMessage.StatusCode);
return null;
}
}
finally
{
SdkInternalOperationsMonitor.Exit();
}
}

/// Set a TokenCredential for this configuration.
/// </summary>
/// <param name="tokenCredential">An instance of Azure.Core.TokenCredential.</param>
public void SetCredential(object tokenCredential) => this.CredentialEnvelope = new ReflectionCredentialEnvelope(tokenCredential);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as a follow up, we could modify the method comment to be more descriptive, and can warn that this throws exception when object is not of type Azure.Core.TokenCredential.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an alternate name could be - SetTokenCredential or SetAzureTokenCredential, to make it more clear that this is an azure only thing.

/// <returns>A valid Azure.Core.AccessToken.</returns>
public string GetToken(CancellationToken cancellationToken = default)
{
SdkInternalOperationsMonitor.Enter();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may be better to leave the job of entering/exiting internal operation to the consumer (like Transmission class)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will investigate this in second PR.

@TimothyMothra TimothyMothra merged commit ad3d952 into develop May 27, 2021
@TimothyMothra TimothyMothra deleted the tilee/feature_aad branch May 27, 2021 02:10
@TimothyMothra TimothyMothra added this to the 2.18 milestone May 28, 2021
tokaplan added a commit to tokaplan/ApplicationInsights-dotnet that referenced this pull request Jul 22, 2021
* Added support for FlushAsync API

* Added more test cases

* Corrections to test case

* fixed merge conflicts

* Fixed an issue with IsEnqueueSuccess

* Bumping CurrentInvariantVersion for QuickPulse. (microsoft#2123)

* Endpoint and ping interval hints for QuickPulseModule.

* Updating changelog.md with the PR link for the change.

* StyleCop error fix.

* Bumping CurrentInvariantVersion for QuickPulse.

* Unit test fixes.

* Update how BuildNumbers are calculated (microsoft#2125)

* Update _GlobalStaticVersion.props

Change to the way we calculate the build number.

Formerly, we calculated builds as the TotalMinutes between DateTime.Now and the semantic version time stamp, divided by 5.
This meant that every 5 minutes the build number changes.
This was hurting nightly nupkgs because our assembly version and packages weren't matching.

This PR changes the calculation to be TotalHours / 12.

* Update release_NupkgAudit.ps1

* Update Changelog, prep 2.17.0-beta1 (microsoft#2126)

* Update release_NupkgAudit.ps1 (microsoft#2128)

* Update release_NupkgAudit.ps1

removing the hardcoded hash.
will put the value in the build definition. This will be easier to update when certs rotate.

* Update release_NupkgAudit.ps1

punctuation

* upgrade log4net 2.0.10 (microsoft#2150)

* Fix: telemetry parent id when using W3C activity format (microsoft#2145)

* Fix telemetry parent id when using W3C activity format

* Add unit tests

* Added InFlightTransmission struct

* Add response duration to TransmissionStatusEventArgs

* Update ChangeLog

* Update profiler and snapshot endpoints
Fixes microsoft#2166

* bump version 2.17 Stable (microsoft#2171)

* bump version

* Update CHANGELOG.md

* finalize public API

* remove outdated NuGet.Config files

* Update CONTRIBUTING.md (microsoft#2177)

* remove comment

* Update Readme.md (microsoft#2182)

Adding Support policy to readme

* Update bug_report.md (microsoft#2183)

* Update bug_report.md

Adding Immediate support policy to the bug template

* Removing item check in serializer

* Fix tests

* New Implementation

* Added Increment to pause storage dequeue

* thread sync support for move transmissions

* Create dependabot.yml (microsoft#2201)

* Fix PropertyFetcher error when used with multiple types (microsoft#2197)

* Fix PropertyFetcher error when used with multiple types

* Fix build errors

Co-authored-by: Timothy Mothra <tilee@microsoft.com>

* remove Microsoft.TestPlatform.TestHost (microsoft#2208)

* Bump Microsoft.NET.Test.Sdk from 16.7.1 to 16.9.4 (microsoft#2206)

* Bump Microsoft.NET.Test.Sdk from 16.7.1 to 16.9.4

Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.7.1 to 16.9.4.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Commits](microsoft/vstest@v16.7.1...v16.9.4)

Signed-off-by: dependabot[bot] <support@github.com>

* Update Microsoft.ApplicationInsights.Isolated.Tests.csproj

remove System.Reflection.Metadata

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Timothy Mothra <tilee@microsoft.com>

* Bump NETStandard.HttpListener from 1.0.2 to 1.0.3.5 (microsoft#2205)

Bumps [NETStandard.HttpListener](https://github.com/StefH/NETStandard.HttpListener) from 1.0.2 to 1.0.3.5.
- [Release notes](https://github.com/StefH/NETStandard.HttpListener/releases)
- [Commits](https://github.com/StefH/NETStandard.HttpListener/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump Newtonsoft.Json from 10.0.3 to 13.0.1 (microsoft#2209)

* Bump Newtonsoft.Json from 10.0.3 to 13.0.1

Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 10.0.3 to 13.0.1.
- [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases)
- [Commits](JamesNK/Newtonsoft.Json@10.0.3...13.0.1)

Signed-off-by: dependabot[bot] <support@github.com>

* Update Microsoft.ApplicationInsights.Tests.csproj

* Update Microsoft.ApplicationInsights.Isolated.Tests.csproj

* Update TelemetryChannel.Nuget.Tests.csproj

* Update TelemetryChannel.Tests.csproj

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Timothy Mothra <tilee@microsoft.com>

* Bump log4net from 2.0.10 to 2.0.12 (microsoft#2204)

Bumps [log4net](https://github.com/apache/logging-log4net) from 2.0.10 to 2.0.12.
- [Release notes](https://github.com/apache/logging-log4net/releases)
- [Changelog](https://github.com/apache/logging-log4net/blob/master/ReleaseInstructions.txt)
- [Commits](apache/logging-log4net@rel/2.0.10...rc/2.0.12)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump System.Text.Encoding.CodePages from 4.3.0 to 5.0.0 (microsoft#2211)

* Bump Microsoft.AspNetCore.Identity from 2.1.1 to 2.1.2 (microsoft#2215)

* Bump Microsoft.AspNetCore.StaticFiles from 2.1.1 to 2.2.0 (microsoft#2216)

* Bump Microsoft.AspNetCore.Mvc.TagHelpers from 2.1.1 to 2.2.0 (microsoft#2212)

* update and consolidate xunit dependencies (microsoft#2222)

* update and consolidate xunit dependencies

* fix xunit analyzer

* Bump MSTest.TestAdapter from 2.1.2 to 2.2.3 (microsoft#2223)

* Bump System.Console from 4.3.0 to 4.3.1 (microsoft#2224)

* Bump Microsoft.AspNetCore.Server.IISIntegration from 2.1.1 to 2.2.1 (microsoft#2226)

* Saving work in progress.

* API changes

* Additional tests

* spaces

* Review changes

* Fix flaky test.

* PR feedback

* InternalsVisibleTo Microsoft.AI.ServerTelemetryChannel (microsoft#2229)

* Add CancellationToken check for MoveTransmissions

* Bump Microsoft.AspNetCore.Server.Kestrel from 1.1.2 to 2.2.0 (microsoft#2207)

* Bump System.Data.SqlClient from 4.7.0 to 4.8.2 (microsoft#2231)

Bumps [System.Data.SqlClient](https://github.com/dotnet/corefx) from 4.7.0 to 4.8.2.
- [Release notes](https://github.com/dotnet/corefx/releases)
- [Commits](https://github.com/dotnet/corefx/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* examples sln (microsoft#2233)

* new solution

* fix path

* additional properties in props

* adding AspNetCore WebApp to Examples

* simplify property

* PR feedback

* Initialization code and entry point for Self Diagnostics Module

* Adding access modifier

* Add APIs as declared API list

* Fix flaky test - FlushAsyncTransmissionWithThrottle (microsoft#2247)

* Add ManualResetEventSlim.Wait

* Fix warning

* general maintenance (microsoft#2250)

* general maintenance

* fix date

* update analyzers (microsoft#2198)

* update analyzers

* remove default case, tests should pass

* fxcop

* cleanup

* testing fix

* remove net452 and net46 from aspnetcore (microsoft#2252)

* remove net452 and net46 from aspnetcore

* changelog

* consolidate package references

* cleanup unnecessary dependencies in AspNetCore SDK (microsoft#2253)

* Move location of Initialization

* [SDL] update packages (microsoft#2243)

* update packages

* update test dependencies

* testing fix for version conflicts

* Update IntegrationTests.Tests.csproj

* cleanup

* cleanup

* Remove "Module" in class name. Change class to internal.

* Update CHANGELOG.md (microsoft#2254)

* Add config parser class for SelfDiagnostics

* Rename SelfDiagnostics class to SelfDiagnosticsInitializer, and SelfDiagnosticsInternals names to SelfDiagnostics.

* Rename test class namespace. Remove xunit dependency.

* Add EventListener for SelfDiagnostics (microsoft#2259)

* Add EventListener for SelfDiagnostics

* Match with EventSource name's prefix

* troubleshooting (microsoft#2264)

* troubleshooting guides

* update

* update

* update

* Update Readme.md

* Update Readme.md

* Update PostTelemetry.ps1

* Update Readme.md

* Encode event and write to file in SelfDiagnosticsEventListener (microsoft#2265)

* Encode event and write to file in SelfDiagnosticsEventListener

* Fix compile error

* Add MemoryMappedFileHandler for SelfDiagnostics (microsoft#2258)

* Add MemoryMappedFileHandler for SelfDiagnostics

* Rename classes and namespace.

* -

* Use CollectionAssert.AreEqual to compare byte[]

* Add circular write logic into MemoryMappedFileHandler class

* Fix trivial compile errors

* Fix trivial compile errors

* Update EventSource method implementation

* Update EventSource method implementation

* -

* Special requirement for last argument in method definition and last parameter for WriteEvent call

* update typo in comment

* Add ConfigRefresher for SelfDiagnostics (microsoft#2262)

* Add MemoryMappedFileHandler for SelfDiagnostics

* Rename classes and namespace.

* -

* Use CollectionAssert.AreEqual to compare byte[]

* Add circular write logic into MemoryMappedFileHandler class

* Add ConfigRefresher for SelfDiagnostics

* Fix trivial compile errors

* Fix trivial compile errors

* Update EventSource method implementation

* Update EventSource method implementation

* -

* Special requirement for last argument in method definition and last parameter for WriteEvent call

* Add new line at end of file

* Change namespace for SelfDiagnosticsInitializer

* Remove redundant using namespace statement.

* Remove blank line

* Cosmetics/technical debt  - use pattern matching (microsoft#2268)

* Fix ReSharper's "Convert 'as' expression type check and the following null check into pattern matching" / Code Smell

* Update changelog with description

* Update Readme and changelog for SelfDiagnostics (microsoft#2267)

* Add Readme and changelog for Self Diagnostics

* Fix failed test cases

* Add changelog entry

* Update troubleshooting/ETW/Readme.md with Self Diagnostics section

* Remove unused code

* Add "as of version 2.18.0"

* Update Self-Diagnostics instructions (microsoft#2271)

* Update Self-Diagnostics instructions

* Update Readme.md

* Update Readme.md

* add Net5.0 to Test Infra and Bask SDK Tests (microsoft#2272)

* add support for net461 to Tests (microsoft#2274)

* fix Test projects dependency, Microsoft.AspNetCore.App (microsoft#2276)

* cleanup frameworks in AspNetCore (microsoft#2278)

* cleanup frameworks in AspNetCore

* fix fxcop

* remove unused dependency (microsoft#2281)

* AAD: Handling Azure.Core.TokenCredential (microsoft#2191)

* Bump Microsoft.AspNetCore.Mvc.Core from 1.0.3 to 1.0.4 (microsoft#2285)

Bumps Microsoft.AspNetCore.Mvc.Core from 1.0.3 to 1.0.4.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* disable flaky tests (microsoft#2289)

* AAD: refactor (microsoft#2288)

* AAD: refactor

* change property to internal

* AAD: with InMemoryChannel (microsoft#2290)

* aad with InMemoryChannel

* Fix AzureSdkDiagnosticListener from crashing user app (microsoft#2294)

* Fix AzureSdkDiagnosticListener from crashing user app

* changelog

* Read Azure SDK Success status (microsoft#2200)

* Read Azure SDK Success status

* cleanup Base SDK Frameworks (microsoft#2280)

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>

* AAD: with QuickPulse (microsoft#2291)

* AAD: with QuickPulse

* AAD: with ServerTelemetryChannel (microsoft#2292)

* AAD: with ServerTelemetryChannel

* bump version 2.18-beta2 (microsoft#2296)

* disable these tests on linux (microsoft#2298)

* Updated link to performance counters docs (microsoft#2301)

* Updated link to performance counters docs

* Update WEB/Src/PerformanceCollector/README.md

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>

* aad: detect type (microsoft#2303)

* Enable the self diagnostics and fix a NullReferenceException bug (microsoft#2302)

* Enable the self diagnostics and fix a NullReferenceException bug

* Fix compilation warnings.

* enable self-diagnostics in example app (microsoft#2305)

* AAD: change to CredentialEnvelope to expose Expiration  (microsoft#2306)

* refactor TransmissionPolicy (microsoft#2311)

* Remove OpenCover. CVE-2018-1285 (microsoft#2313)

* Update Microsoft.Extensions.Logging to 2.1.1

* AAD: new AuthenticationTransmissionPolicy for retry scenarios. (microsoft#2312)

* update version for beta3 (microsoft#2316)

* AAD: Misc changes (microsoft#2317)

* initialize cache inside constructor

* remove todo. not pursing caching right now

* cleanup comment

* update changelog

* Update ReflectionCredentialEnvelope.cs

* log to indicated Authentication Policy caught the response from ingestion (microsoft#2319)

* Update linux-build.yml (microsoft#2329)

update version of dotnet 5

* Self-Diagnostics: include datetimestamp in filename (microsoft#2325)

* include datetimestamp in self-diagnostics filename

* come review comments

* update readme

* update readme

* Update Readme.md

* Update CHANGELOG.md (microsoft#2332)

* prune public api (microsoft#2336)

* prep 2.18 (microsoft#2337)

* Tilee/examples (microsoft#2339)

* move example projects to root. change to project reference

* update packages

* remove release config

* rename projects

* build definition for examples solution

* cleanup yml

* fix yml

* test fix for yml

* test fix yml

* Update examples-sanity.yml (microsoft#2340)

correct branch name

Co-authored-by: Rajkumar Rangaraj <rajrang@microsoft.com>
Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
Co-authored-by: Timothy Mothra <tilee@microsoft.com>
Co-authored-by: ylabade <64366368+ylabade@users.noreply.github.com>
Co-authored-by: Paul Harrington <pharring@microsoft.com>
Co-authored-by: Paul Harrington <pharring@users.noreply.github.com>
Co-authored-by: Oskar Klintrot <oskar.klintrot@gmail.com>
Co-authored-by: ank3it <anksr@microsoft.com>
Co-authored-by: James Newton-King <james@newtonking.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: xiang17 <xili9@microsoft.com>
Co-authored-by: Martin <modermatt@tuta.io>
Co-authored-by: Pavel Krymets <pavel@krymets.com>
Co-authored-by: Lev Yastrebov <36070899+LevYas@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants