-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from wdolek/feature/introduce-integration-tests
Introduce integration tests
- Loading branch information
Showing
10 changed files
with
332 additions
and
5 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
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
25 changes: 25 additions & 0 deletions
25
W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests/README.md
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,25 @@ | ||
## W4k AWS Secrets Manager, Integration tests | ||
|
||
In order to run the integration tests, you need to have a valid AWS credentials set up on your machine. | ||
Integration tests require `w4ktest@admin` profile (see [`SecretsManagerTestFixture.cs`](./SecretsManagerTestFixture.cs)), it must be set up in your AWS credentials file (`~/.aws/credentials`). | ||
|
||
```ini | ||
[w4ktest] | ||
aws_access_key_id = 00000000000000000000 | ||
aws_secret_access_key = 0000000000000000000000000000000000000000 | ||
aws_session_token = ... | ||
account = ... | ||
role = ... | ||
|
||
[w4ktest@admin] | ||
role_arn = arn:aws:iam::000000000000:role/my-role@admin | ||
source_profile = w4ktest | ||
``` | ||
|
||
Once credentials are set up, you can run the integration tests as any other tests in the solution. | ||
|
||
To run only unit tests (and skip integration tests), filter out tests by category: | ||
|
||
```bash | ||
dotnet test --filter "TestCategory!=Integration" | ||
``` |
173 changes: 173 additions & 0 deletions
173
...ons.Configuration.Aws.SecretsManager.IntegrationTests/SecretsManagerConfigSourceShould.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,173 @@ | ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests; | ||
|
||
[Category("Integration")] | ||
public class SecretsManagerConfigSourceShould | ||
{ | ||
[Test] | ||
public void ThrowWhenSecretNotFound() | ||
{ | ||
// act & assert | ||
Assert.Throws<SecretNotFoundException>( | ||
() => | ||
{ | ||
new ConfigurationBuilder().AddSecretsManager( | ||
"w4k/awssm/unknown-secret-mandatory", | ||
SecretsManagerTestFixture.SecretsManagerClient) | ||
.Build(); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void NotThrowWhenSecretIsOptional() | ||
{ | ||
// act & assert | ||
IConfiguration config = null!; | ||
Assert.DoesNotThrow( | ||
() => | ||
{ | ||
config = new ConfigurationBuilder().AddSecretsManager( | ||
"w4k/awssm/unknown-secret-optional", | ||
SecretsManagerTestFixture.SecretsManagerClient, | ||
c => c.IsOptional = true) | ||
.Build(); | ||
}); | ||
|
||
Assert.That(config, Is.Not.Null); | ||
CollectionAssert.IsEmpty(config.GetChildren()); | ||
} | ||
|
||
[Test] | ||
public void FetchSecrets() | ||
{ | ||
// arrange | ||
var expected = new KeyValuePair<string, string>[] | ||
{ | ||
new("ClientId", "my_client_id"), | ||
new("ClientSecret", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"), | ||
}; | ||
|
||
// act | ||
var config = new ConfigurationBuilder().AddSecretsManager( | ||
SecretsManagerTestFixture.KeyValueSecretName, | ||
SecretsManagerTestFixture.SecretsManagerClient) | ||
.Build(); | ||
|
||
var secrets = config.AsEnumerable().ToList(); | ||
|
||
// act | ||
Assert.That(secrets, Has.Count.EqualTo(2)); | ||
CollectionAssert.AreEquivalent(expected, secrets); | ||
} | ||
|
||
[Test] | ||
public void FetchSecretsWithPrefix() | ||
{ | ||
// arrange | ||
var expected = new KeyValuePair<string, string?>[] | ||
{ | ||
new("App", null), | ||
new("App:Secrets", null), | ||
new("App:Secrets:ClientId", "my_client_id"), | ||
new("App:Secrets:ClientSecret", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"), | ||
}; | ||
|
||
// act | ||
var config = new ConfigurationBuilder().AddSecretsManager( | ||
SecretsManagerTestFixture.KeyValueSecretName, | ||
SecretsManagerTestFixture.SecretsManagerClient, | ||
c => c.ConfigurationKeyPrefix = "App:Secrets") | ||
.Build(); | ||
|
||
var secrets = config.AsEnumerable().ToList(); | ||
|
||
// assert | ||
CollectionAssert.AreEquivalent(expected, secrets); | ||
} | ||
|
||
[Test] | ||
public void FetchSecretsWithKeyTransformation() | ||
{ | ||
// arrange | ||
var expected = new KeyValuePair<string, string>[] | ||
{ | ||
new("id", "my_client_id"), | ||
new("secret", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"), | ||
}; | ||
|
||
var customKeyTransformer = new TestKeyTransformer(s => s.Replace("Client", "").ToLowerInvariant()); | ||
|
||
// act | ||
var config = new ConfigurationBuilder().AddSecretsManager( | ||
SecretsManagerTestFixture.KeyValueSecretName, | ||
SecretsManagerTestFixture.SecretsManagerClient, | ||
c => c.KeyTransformers.Add(customKeyTransformer)) | ||
.Build(); | ||
|
||
var secrets = config.AsEnumerable().ToList(); | ||
|
||
// act | ||
CollectionAssert.AreEquivalent(expected, secrets); | ||
} | ||
|
||
[Test] | ||
public void FetchComplexJsonSecret() | ||
{ | ||
// arrange | ||
var expected = new KeyValuePair<string, string?>[] | ||
{ | ||
new("MyService", null), | ||
new("MyService:Username", "saanvis"), | ||
new("ApiKeys", null), | ||
new("ApiKeys:Citizenship", "rosebud"), | ||
new("ApiKeys:Universe", "42"), | ||
new("PIN", null), | ||
new("PIN:0", "5"), | ||
new("PIN:1", "5"), | ||
new("PIN:2", "5"), | ||
new("PIN:3", "2"), | ||
new("PIN:4", "3"), | ||
new("PIN:5", "6"), | ||
new("PIN:6", "8"), | ||
}; | ||
|
||
// act | ||
var config = new ConfigurationBuilder().AddSecretsManager( | ||
SecretsManagerTestFixture.ComplexSecretName, | ||
SecretsManagerTestFixture.SecretsManagerClient) | ||
.Build(); | ||
|
||
var secrets = config.AsEnumerable().ToList(); | ||
|
||
// assert | ||
CollectionAssert.AreEquivalent(expected, secrets); | ||
} | ||
|
||
[Test] | ||
public void FetchMultipleSecrets() | ||
{ | ||
// act | ||
var config = new ConfigurationBuilder().AddSecretsManager( | ||
[SecretsManagerTestFixture.KeyValueSecretName, SecretsManagerTestFixture.ComplexSecretName], | ||
SecretsManagerTestFixture.SecretsManagerClient) | ||
.Build(); | ||
|
||
var secrets = config.AsEnumerable().ToList(); | ||
|
||
// assert | ||
Assert.That(secrets, Has.Count.EqualTo(15)); | ||
} | ||
|
||
private class TestKeyTransformer : IConfigurationKeyTransformer | ||
{ | ||
private readonly Func<string,string> _transform; | ||
|
||
public TestKeyTransformer(Func<string, string> transform) | ||
{ | ||
_transform = transform; | ||
} | ||
|
||
public string Transform(string key) => _transform(key); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
...Extensions.Configuration.Aws.SecretsManager.IntegrationTests/SecretsManagerTestFixture.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,65 @@ | ||
using Amazon; | ||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.SecretsManager; | ||
using Amazon.SecretsManager.Model; | ||
|
||
namespace W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests; | ||
|
||
[SetUpFixture] | ||
public class SecretsManagerTestFixture | ||
{ | ||
private const string AwsProfileName = "w4ktest@admin"; | ||
|
||
public static IAmazonSecretsManager SecretsManagerClient { get; private set; } = null!; | ||
|
||
public static string KeyValueSecretName { get; private set; } = ""; | ||
public static string ComplexSecretName { get; private set; } = ""; | ||
|
||
[OneTimeSetUp] | ||
public void OneTimeSetUp() | ||
{ | ||
var storeChain = new CredentialProfileStoreChain(); | ||
if (!storeChain.TryGetAWSCredentials(AwsProfileName, out var credentials)) | ||
{ | ||
throw new InvalidOperationException($"""Unable to get AWS credentials using "{AwsProfileName}" profile."""); | ||
} | ||
|
||
var guid = Guid.NewGuid().ToString("N")[^8..]; | ||
KeyValueSecretName = $"{TestSecrets.KeyValueSecretName}/{guid}"; | ||
ComplexSecretName = $"{TestSecrets.ComplexSecretName}/{guid}"; | ||
|
||
var client = new AmazonSecretsManagerClient(credentials, RegionEndpoint.EUWest1); | ||
CreateSecret(client, KeyValueSecretName, TestSecrets.KeyValueJson).GetAwaiter().GetResult(); | ||
CreateSecret(client, ComplexSecretName, TestSecrets.ComplexJson).GetAwaiter().GetResult(); | ||
|
||
SecretsManagerClient = client; | ||
} | ||
|
||
[OneTimeTearDown] | ||
public void OneTimeTearDown() | ||
{ | ||
var client = SecretsManagerClient; | ||
DeleteSecret(client, KeyValueSecretName).GetAwaiter().GetResult(); | ||
DeleteSecret(client, ComplexSecretName).GetAwaiter().GetResult(); | ||
|
||
client.Dispose(); | ||
SecretsManagerClient = null!; | ||
} | ||
|
||
private static Task CreateSecret(IAmazonSecretsManager client, string secretName, string secretValue) => | ||
client.CreateSecretAsync( | ||
new CreateSecretRequest | ||
{ | ||
Name = secretName, | ||
SecretString = secretValue, | ||
Description = "W4k.Extensions.Configuration.Aws.SecretsManager integration secret" | ||
}); | ||
|
||
private static Task DeleteSecret(IAmazonSecretsManager client, string secretName) => | ||
client.DeleteSecretAsync( | ||
new DeleteSecretRequest | ||
{ | ||
SecretId = secretName, | ||
ForceDeleteWithoutRecovery = true, | ||
}); | ||
} |
24 changes: 24 additions & 0 deletions
24
W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests/TestSecrets.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,24 @@ | ||
namespace W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests; | ||
|
||
public static class TestSecrets | ||
{ | ||
public const string KeyValueSecretName = "w4k/awssm/key-value-secret"; | ||
public const string KeyValueJson = """ | ||
{ | ||
"ClientId": "my_client_id", | ||
"ClientSecret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" | ||
} | ||
"""; | ||
|
||
public const string ComplexSecretName = "w4k/awssm/complex-secret"; | ||
public const string ComplexJson = """ | ||
{ | ||
"MyService__Username": "saanvis", | ||
"ApiKeys": { | ||
"Citizenship": "rosebud", | ||
"Universe": "42" | ||
}, | ||
"PIN": [ 5, 5, 5, 2, 3, 6, 8 ] | ||
} | ||
"""; | ||
} |
28 changes: 28 additions & 0 deletions
28
....IntegrationTests/W4k.Extensions.Configuration.Aws.SecretsManager.IntegrationTests.csproj
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,28 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.2"/> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0"/> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/> | ||
<PackageReference Include="NUnit" Version="3.14.0"/> | ||
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="NUnit.Framework"/> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\W4k.Extensions.Configuration.Aws.SecretsManager\W4k.Extensions.Configuration.Aws.SecretsManager.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
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
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