-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test isn't implementing logic of #1820 yet, just replicating an existing test to ensure the test runner passes initially. Created in a new test class to reduce changes of merge conflicts, but extracted out shared logic from existing test class.
- Loading branch information
1 parent
49ac53a
commit 8cbbeb4
Showing
4 changed files
with
189 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
namespace Azure.DataApiBuilder.Service.Tests.Configuration; | ||
|
||
internal static class ConfigurationEndpoints | ||
{ | ||
// TODO: Remove the old endpoint once we've updated all callers to use the new one. | ||
public const string CONFIGURATION_ENDPOINT = "/configuration"; | ||
public const string CONFIGURATION_ENDPOINT_V2 = "/configuration/v2"; | ||
} |
144 changes: 144 additions & 0 deletions
144
src/Service.Tests/Configuration/ConfigurationJsonBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IdentityModel.Tokens.Jwt; | ||
using System.IO; | ||
using System.Net.Http.Json; | ||
using System.Security.Claims; | ||
using System.Text; | ||
using Azure.DataApiBuilder.Config; | ||
using Azure.DataApiBuilder.Config.ObjectModel; | ||
using Azure.DataApiBuilder.Service.Controllers; | ||
using Microsoft.IdentityModel.Tokens; | ||
using static Azure.DataApiBuilder.Config.FileSystemRuntimeConfigLoader; | ||
using static Azure.DataApiBuilder.Service.Tests.Configuration.ConfigurationEndpoints; | ||
|
||
namespace Azure.DataApiBuilder.Service.Tests.Configuration; | ||
|
||
/// <summary> | ||
/// Provides methods to build the json content for the configuration endpoint. | ||
/// </summary> | ||
internal static class ConfigurationJsonBuilder | ||
{ | ||
public const string COSMOS_ENVIRONMENT = TestCategory.COSMOSDBNOSQL; | ||
public const string COSMOS_DATABASE_NAME = "config_db"; | ||
|
||
public static JsonContent GetJsonContentForCosmosConfigRequest(string endpoint, string config = null, bool useAccessToken = false) | ||
{ | ||
if (CONFIGURATION_ENDPOINT == endpoint) | ||
{ | ||
ConfigurationPostParameters configParams = GetCosmosConfigurationParameters(); | ||
if (config is not null) | ||
{ | ||
configParams = configParams with { Configuration = config }; | ||
} | ||
|
||
if (useAccessToken) | ||
{ | ||
configParams = configParams with | ||
{ | ||
ConnectionString = "AccountEndpoint=https://localhost:8081/;", | ||
AccessToken = GenerateMockJwtToken() | ||
}; | ||
} | ||
|
||
return JsonContent.Create(configParams); | ||
} | ||
else if (CONFIGURATION_ENDPOINT_V2 == endpoint) | ||
{ | ||
ConfigurationPostParametersV2 configParams = GetCosmosConfigurationParametersV2(); | ||
if (config != null) | ||
{ | ||
configParams = configParams with { Configuration = config }; | ||
} | ||
|
||
if (useAccessToken) | ||
{ | ||
// With an invalid access token, when a new instance of CosmosClient is created with that token, it | ||
// won't throw an exception. But when a graphql request is coming in, that's when it throws a 401 | ||
// exception. To prevent this, CosmosClientProvider parses the token and retrieves the "exp" property | ||
// from the token, if it's not valid, then we will throw an exception from our code before it | ||
// initiating a client. Uses a valid fake JWT access token for testing purposes. | ||
RuntimeConfig overrides = new( | ||
Schema: null, | ||
DataSource: new DataSource(DatabaseType.CosmosDB_NoSQL, "AccountEndpoint=https://localhost:8081/;", new()), | ||
Runtime: null, | ||
Entities: new(new Dictionary<string, Entity>())); | ||
|
||
configParams = configParams with | ||
{ | ||
ConfigurationOverrides = overrides.ToJson(), | ||
AccessToken = GenerateMockJwtToken() | ||
}; | ||
} | ||
|
||
return JsonContent.Create(configParams); | ||
} | ||
else | ||
{ | ||
throw new ArgumentException($"Unexpected configuration endpoint. {endpoint}"); | ||
} | ||
} | ||
|
||
private static string GenerateMockJwtToken() | ||
{ | ||
string mySecret = "PlaceholderPlaceholder"; | ||
SymmetricSecurityKey mySecurityKey = new(Encoding.ASCII.GetBytes(mySecret)); | ||
|
||
JwtSecurityTokenHandler tokenHandler = new(); | ||
SecurityTokenDescriptor tokenDescriptor = new() | ||
{ | ||
Subject = new ClaimsIdentity(new Claim[] { }), | ||
Expires = DateTime.UtcNow.AddMinutes(5), | ||
Issuer = "http://mysite.com", | ||
Audience = "http://myaudience.com", | ||
SigningCredentials = new SigningCredentials(mySecurityKey, SecurityAlgorithms.HmacSha256Signature) | ||
}; | ||
|
||
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); | ||
return tokenHandler.WriteToken(token); | ||
} | ||
|
||
public static ConfigurationPostParameters GetCosmosConfigurationParameters() | ||
{ | ||
RuntimeConfig configuration = ReadCosmosConfigurationFromFile(); | ||
return new( | ||
configuration.ToJson(), | ||
File.ReadAllText("schema.gql"), | ||
$"AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;Database={COSMOS_DATABASE_NAME}", | ||
AccessToken: null); | ||
} | ||
|
||
private static ConfigurationPostParametersV2 GetCosmosConfigurationParametersV2() | ||
{ | ||
RuntimeConfig configuration = ReadCosmosConfigurationFromFile(); | ||
RuntimeConfig overrides = new( | ||
Schema: null, | ||
DataSource: new DataSource(DatabaseType.CosmosDB_NoSQL, $"AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;Database={COSMOS_DATABASE_NAME}", new()), | ||
Runtime: null, | ||
Entities: new(new Dictionary<string, Entity>())); | ||
|
||
return new( | ||
configuration.ToJson(), | ||
overrides.ToJson(), | ||
File.ReadAllText("schema.gql"), | ||
AccessToken: null); | ||
} | ||
|
||
private static RuntimeConfig ReadCosmosConfigurationFromFile() | ||
{ | ||
string cosmosFile = $"{CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}"; | ||
|
||
string configurationFileContents = File.ReadAllText(cosmosFile); | ||
if (!RuntimeConfigLoader.TryParseConfig(configurationFileContents, out RuntimeConfig config)) | ||
{ | ||
throw new Exception("Failed to parse configuration file."); | ||
} | ||
|
||
// The Schema file isn't provided in the configuration file when going through the configuration endpoint so we're removing it. | ||
config.DataSource.Options.Remove("Schema"); | ||
return config; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Json; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.TestHost; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using static Azure.DataApiBuilder.Service.Tests.Configuration.ConfigurationEndpoints; | ||
using static Azure.DataApiBuilder.Service.Tests.Configuration.ConfigurationJsonBuilder; | ||
|
||
namespace Azure.DataApiBuilder.Service.Tests.Configuration; | ||
|
||
[TestClass] | ||
public class LoadConfigViaEndpointTests | ||
{ | ||
[TestMethod("Testing that environment variables can be replaced at runtime not only when config is loaded."), TestCategory(TestCategory.COSMOSDBNOSQL)] | ||
[DataRow(CONFIGURATION_ENDPOINT_V2)] | ||
public async Task CanLoadConfigWithMissingEnvironmentVariables(string configurationEndpoint) | ||
{ | ||
TestServer server = new(Program.CreateWebHostFromInMemoryUpdateableConfBuilder(Array.Empty<string>())); | ||
HttpClient httpClient = server.CreateClient(); | ||
|
||
JsonContent content = GetJsonContentForCosmosConfigRequest(configurationEndpoint); | ||
|
||
HttpResponseMessage postResult = | ||
await httpClient.PostAsync(configurationEndpoint, content); | ||
Assert.AreEqual(HttpStatusCode.OK, postResult.StatusCode); | ||
} | ||
} |