Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/metricsadvisor/Azure.AI.MetricsAdvisor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- Moved `DatasourceCredential`, `DataFeedSource`, `NotificationHook`, and all of their concrete child types to the `Azure.AI.MetricsAdvisor.Administration` namespace.
- Moved `MetricFeedback` and all of its concrete child types to the `Azure.AI.MetricsAdvisor` namespace.
- Changed order of parameters of `MetricsAdvisorClient.GetMetricEnrichedSeriesData`. Now, `detectionConfigurationId` appears first.
- In `MetricsAdvisorKeyCredential`, merged `UpdateSubscriptionKey` and `UpdateApiKey` into a single method, `Update`, to make it an atomic operation.

## 1.0.0-beta.4 (2021-06-07)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,7 @@ public enum ServiceVersion
public partial class MetricsAdvisorKeyCredential
{
public MetricsAdvisorKeyCredential(string subscriptionKey, string apiKey) { }
public void UpdateApiKey(string apiKey) { }
public void UpdateSubscriptionKey(string subscriptionKey) { }
public void Update(string subscriptionKey, string apiKey) { }
}
}
namespace Azure.AI.MetricsAdvisor.Administration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,59 +13,40 @@ namespace Azure.AI.MetricsAdvisor
/// </summary>
public class MetricsAdvisorKeyCredential
{
private string _subscriptionKey;

private string _apiKey;
private Tuple<string, string> _keyPair;

/// <summary>
/// Initializes a new instance of the <see cref="MetricsAdvisorKeyCredential"/> class.
/// </summary>
/// <param name="subscriptionKey">The subscription key to use to authenticate with the Azure service.</param>
/// <param name="apiKey">The API key to use to authenticate the user with the Metrics Advisor service. Used to identify administrators.</param>
/// <param name="apiKey">The API key to use to authenticate the user with the Metrics Advisor service. Used to differentiate administrators and viewers.</param>
/// <exception cref="ArgumentNullException"><paramref name="subscriptionKey"/> or <paramref name="apiKey"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="subscriptionKey"/> or <paramref name="apiKey"/> is empty.</exception>
public MetricsAdvisorKeyCredential(string subscriptionKey, string apiKey)
{
UpdateSubscriptionKey(subscriptionKey);
UpdateApiKey(apiKey);
}

internal string SubscriptionKey
{
get => Volatile.Read(ref _subscriptionKey);
private set => Volatile.Write(ref _subscriptionKey, value);
Update(subscriptionKey, apiKey);
}

internal string ApiKey
internal Tuple<string, string> KeyPair
{
get => Volatile.Read(ref _apiKey);
private set => Volatile.Write(ref _apiKey, value);
get => Volatile.Read(ref _keyPair);
private set => Volatile.Write(ref _keyPair, value);
}

/// <summary>
/// Updates the subscription key. This is intended to be used when you've regenerated
/// your subscription key and want to update long lived clients.
/// Updates the subscription and API keys. This is intended to be used when you've regenerated
/// your keys and want to update long lived clients.
/// </summary>
/// <param name="subscriptionKey">The subscription key to authenticate the service against.</param>
/// <exception cref="ArgumentNullException"><paramref name="subscriptionKey"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="subscriptionKey"/> is empty.</exception>
public void UpdateSubscriptionKey(string subscriptionKey)
/// <param name="apiKey">The API key to use to authenticate the user with the Metrics Advisor service. Used to differentiate administrators and viewers.</param>
/// <exception cref="ArgumentNullException"><paramref name="subscriptionKey"/> or <paramref name="apiKey"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="subscriptionKey"/> or <paramref name="apiKey"/> is empty.</exception>
public void Update(string subscriptionKey, string apiKey)
{
Argument.AssertNotNullOrEmpty(subscriptionKey, nameof(subscriptionKey));
SubscriptionKey = subscriptionKey;
}

/// <summary>
/// Updates the API key. This is intended to be used when you've regenerated your
/// API key and want to update long lived clients.
/// </summary>
/// <param name="apiKey">The API key to use to authenticate the user with the Metrics Advisor service. Used to identify administrators.</param>
/// <exception cref="ArgumentNullException"><paramref name="apiKey"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="apiKey"/> is empty.</exception>
public void UpdateApiKey(string apiKey)
{
Argument.AssertNotNullOrEmpty(apiKey, nameof(apiKey));
ApiKey = apiKey;

KeyPair = Tuple.Create(subscriptionKey, apiKey);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Azure.Core;
using Azure.Core.Pipeline;

Expand All @@ -20,8 +21,10 @@ public override void OnSendingRequest(HttpMessage message)
{
base.OnSendingRequest(message);

message.Request.Headers.SetValue(Constants.SubscriptionAuthorizationHeader, _credential.SubscriptionKey);
message.Request.Headers.SetValue(Constants.ApiAuthorizationHeader, _credential.ApiKey);
Tuple<string, string> keyPair = _credential.KeyPair;

message.Request.Headers.SetValue(Constants.SubscriptionAuthorizationHeader, keyPair.Item1);
message.Request.Headers.SetValue(Constants.ApiAuthorizationHeader, keyPair.Item2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using System.Threading.Tasks;
using Azure.AI.MetricsAdvisor.Administration;
using Azure.AI.MetricsAdvisor.Models;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,25 @@ public MockClientTestBase(bool isAsync) : base(isAsync)

public string FakeGuid => "00000000-0000-0000-0000-000000000000";

public MetricsAdvisorClient CreateInstrumentedClient(MockResponse response)
public MetricsAdvisorClient CreateInstrumentedClient(MockResponse response) =>
CreateInstrumentedClient(new MockTransport(response));

public MetricsAdvisorClient CreateInstrumentedClient(MockTransport transport, MetricsAdvisorKeyCredential credential = null)
{
var fakeEndpoint = new Uri("http://notreal.azure.com");
var fakeCredential = new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");
var options = new MetricsAdvisorClientsOptions() { Transport = new MockTransport(response) };
var fakeCredential = credential ?? new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");
var options = new MetricsAdvisorClientsOptions() { Transport = transport };

return InstrumentClient(new MetricsAdvisorClient(fakeEndpoint, fakeCredential, options));
}

public MetricsAdvisorAdministrationClient CreateInstrumentedAdministrationClient(MockResponse response) =>
CreateInstrumentedAdministrationClient(new MockTransport(response));

public MetricsAdvisorAdministrationClient CreateInstrumentedAdministrationClient(MockTransport transport)
public MetricsAdvisorAdministrationClient CreateInstrumentedAdministrationClient(MockTransport transport, MetricsAdvisorKeyCredential credential = null)
{
var fakeEndpoint = new Uri("http://notreal.azure.com");
var fakeCredential = new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");
var fakeCredential = credential ?? new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");
var options = new MetricsAdvisorClientsOptions() { Transport = transport };

return InstrumentClient(new MetricsAdvisorAdministrationClient(fakeEndpoint, fakeCredential, options));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.AI.MetricsAdvisor.Administration;
using Azure.Core.TestFramework;
using NUnit.Framework;

namespace Azure.AI.MetricsAdvisor.Tests
{
public class MetricsAdvisorKeyCredentialTests : MockClientTestBase
{
public MetricsAdvisorKeyCredentialTests(bool isAsync) : base(isAsync)
{
}

[Test]
public async Task MetricsAdvisorKeyCredentialSendsSecretInMetricsAdvisorClient()
{
MockResponse response = new MockResponse(200);
response.SetContent("{}");

MockTransport mockTransport = new MockTransport(response);

string expectedSubscriptionKey = "fakeSubscriptionKey";
string expectedApiKey = "fakeApiKey";
MetricsAdvisorKeyCredential credential = new MetricsAdvisorKeyCredential(expectedSubscriptionKey, expectedApiKey);

MetricsAdvisorClient client = CreateInstrumentedClient(mockTransport, credential);

IAsyncEnumerator<MetricFeedback> asyncEnumerator = client.GetAllFeedbackAsync(FakeGuid).GetAsyncEnumerator();
await asyncEnumerator.MoveNextAsync();

MockRequest request = mockTransport.Requests.First();

Assert.That(request.Headers.TryGetValue(Constants.SubscriptionAuthorizationHeader, out string subscriptionKey));
Assert.That(request.Headers.TryGetValue(Constants.ApiAuthorizationHeader, out string apiKey));

Assert.That(subscriptionKey, Is.EqualTo(expectedSubscriptionKey));
Assert.That(apiKey, Is.EqualTo(expectedApiKey));
}

[Test]
public async Task MetricsAdvisorKeyCredentialSendsSecretInMetricsAdvisorAdministrationClient()
{
MockResponse response = new MockResponse(204);
MockTransport mockTransport = new MockTransport(response);

string expectedSubscriptionKey = "fakeSubscriptionKey";
string expectedApiKey = "fakeApiKey";
MetricsAdvisorKeyCredential credential = new MetricsAdvisorKeyCredential(expectedSubscriptionKey, expectedApiKey);

MetricsAdvisorAdministrationClient adminClient = CreateInstrumentedAdministrationClient(mockTransport, credential);

await adminClient.DeleteAlertConfigurationAsync(FakeGuid);

MockRequest request = mockTransport.Requests.First();

Assert.That(request.Headers.TryGetValue(Constants.SubscriptionAuthorizationHeader, out string subscriptionKey));
Assert.That(request.Headers.TryGetValue(Constants.ApiAuthorizationHeader, out string apiKey));

Assert.That(subscriptionKey, Is.EqualTo(expectedSubscriptionKey));
Assert.That(apiKey, Is.EqualTo(expectedApiKey));
}

[Test]
public async Task MetricsAdvisorKeyCredentialUpdatesSecret()
{
MockResponse response = new MockResponse(204);
MockTransport mockTransport = new MockTransport(response);
MetricsAdvisorKeyCredential credential = new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");

string expectedSubscriptionKey = "newFakeSubscriptionKey";
string expectedApiKey = "newFakeApiKey";

MetricsAdvisorAdministrationClient adminClient = CreateInstrumentedAdministrationClient(mockTransport, credential);

credential.Update(expectedSubscriptionKey, expectedApiKey);

await adminClient.DeleteAlertConfigurationAsync(FakeGuid);

MockRequest request = mockTransport.Requests.First();

Assert.That(request.Headers.TryGetValue(Constants.SubscriptionAuthorizationHeader, out string subscriptionKey));
Assert.That(request.Headers.TryGetValue(Constants.ApiAuthorizationHeader, out string apiKey));

Assert.That(subscriptionKey, Is.EqualTo(expectedSubscriptionKey));
Assert.That(apiKey, Is.EqualTo(expectedApiKey));
}
}
}