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

Feature/58 aws options from appsettings #61

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
72 changes: 71 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,76 @@ builder.AddSecretsManager(configurator: options =>

```

## Configuration via appsettings.json
Many options can be specified in a JSON file rather than hardcoded within the app. To do so,
the `ReadFromConfigSection` method should be called, like so:
Comment on lines +210 to +212
Copy link
Owner

Choose a reason for hiding this comment

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

I would rather specify that many options can be specified using the Microsoft Configuration system without limiting to the JSON file. After all, the configuration values can be provided using other providers.


```csharp
builder.AddSecretsManager(configurator: options =>
{
options.ReadFromConfigSection();
Copy link
Owner

Choose a reason for hiding this comment

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

Align to new name.

});
```

By default, this library will assume your options are in a config section named `SecretsManager`,
however you can override this behaviour by specifying the name of your config section when calling the method,
e.g. `options.ReadFromConfigSection("MySecretsManagerConfig");`

### Example appsettings config section
The following shows all the options that can be configured via appsettings. Note that each property within this section is optional.
```json
{
"SecretsManager": {
"Profile": "MySecretsProfile",
"Region": "eu-west-1",
"ProfilesLocation": "C:\\Users\\MyUser\\.aws\\",
"PollingIntervalInSeconds": 60,
"AcceptedSecretArns": [
"arn:example:01-abcxyz",
"arn:example:02",
"unique-secret-name"
],
"ListSecretsFilters": [
{
"Key": "Name",
"Values": [ "Value1", "Value2" ]
}
]
}
}
```

### Mixing hardcoded and appsettings configuration
It's possible to configure this library to use options both from code and from a configuration source such as appsettings.
To do so, call the `ReadFromConfigSection` method as above, and also specify the configuration that you want to use in code.
For example:

```csharp
builder.AddSecretsManager(configurator: options =>
{
options.ReadFromConfigSection();
options.KeyGenerator = (entry, key) => key.ToUpper();
options.AcceptedSecretArns = new[]
{
"MySecretARN1",
}
});

```

Note that if `AcceptedSecretArns` is specified both in code-based and json-based configuration, the collections will be combined
and both will be used. The same applies for the `ListSecretsFilters` collection. For all other properties, the code-based configuration
will take precedence.
Comment on lines +268 to +269
Copy link
Owner

Choose a reason for hiding this comment

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

Is it really "code-based precedence will take precedence" or simply "last called wins"?


### Falling back on AWS config section
It's common for C# applications that interact with AWS to use a config section called `AWS`, that specifies various options
such as the credentials profile that should be used, the location of the credentials profile file, and the region to use.
If this library has been configured to `ReadFromConfigSection`, it will also check for the `AWS` config section,
and will fall back on the `Profile`, `Region` and `ProfilesLocation` specified in the `AWS` section if they are
not present in the `SecretsManager` section.

You can find an example application that demonstrates how to use json based configuration [here](/samples/Sample).

## Versioning

This library follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html) for the public releases (published to the [nuget.org](https://www.nuget.org/)).
Expand All @@ -215,7 +285,7 @@ This library follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.h

This project uses [Cake](https://cakebuild.net/) as a build engine.

If you would like to build this project locally, just execute the `build.cake` script.
If you would like to build this project locally, just exe7ute the `build.cake` script.
Comment on lines -218 to +288
Copy link
Owner

Choose a reason for hiding this comment

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

I guess this is a typo


You can do it by using the .NET tool created by CAKE authors and use it to execute the build script.

Expand Down
15 changes: 15 additions & 0 deletions SecretsManager.sln
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample6", "samples\Sample6\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleWeb", "samples\SampleWeb\SampleWeb.csproj", "{713BFD7D-75C3-452E-A424-437348D6C5FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample7", "samples\Sample7\Sample7.csproj", "{F4801618-8558-4C92-B05A-2E7380DBD662}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -145,6 +147,18 @@ Global
{713BFD7D-75C3-452E-A424-437348D6C5FF}.Release|x64.Build.0 = Release|Any CPU
{713BFD7D-75C3-452E-A424-437348D6C5FF}.Release|x86.ActiveCfg = Release|Any CPU
{713BFD7D-75C3-452E-A424-437348D6C5FF}.Release|x86.Build.0 = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|x64.ActiveCfg = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|x64.Build.0 = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|x86.ActiveCfg = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Debug|x86.Build.0 = Debug|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|Any CPU.Build.0 = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|x64.ActiveCfg = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|x64.Build.0 = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|x86.ActiveCfg = Release|Any CPU
{F4801618-8558-4C92-B05A-2E7380DBD662}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -159,6 +173,7 @@ Global
{7756FF98-349B-4E15-82D6-523E8AA59D72} = {101F77F3-9063-4287-AB1D-20DD19F171A6}
{0C856672-08BA-4E06-B69E-0C4526FB8F54} = {101F77F3-9063-4287-AB1D-20DD19F171A6}
{713BFD7D-75C3-452E-A424-437348D6C5FF} = {101F77F3-9063-4287-AB1D-20DD19F171A6}
{F4801618-8558-4C92-B05A-2E7380DBD662} = {101F77F3-9063-4287-AB1D-20DD19F171A6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A1CF3BDB-61B4-458C-960A-25CBC7E5EB83}
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ environment:
AWS_REGION: us-east-1
CAKE_SETTINGS_SKIPPACKAGEVERSIONCHECK: "true"

image: Visual Studio 2019
image: Visual Studio 2022

cache:
- '%LocalAppData%\NuGet\v3-cache'
Expand Down
10 changes: 9 additions & 1 deletion build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,15 @@ Task("UploadTestsToAppVeyor")
foreach (var file in testResultFiles)
{
Information($"\tUploading {file.GetFilename()}");
AppVeyor.UploadTestResults(file, AppVeyorTestResultsType.MSTest);

try
{
AppVeyor.UploadTestResults(file, AppVeyorTestResultsType.MSTest);
}
catch
{
Error($"Failed to upload {file.GetFilename()}");
}
}
});

Expand Down
35 changes: 35 additions & 0 deletions samples/Sample7/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.Extensions.Configuration;

namespace Sample7
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder();

/*
* Add some configuration source.
* In this case, we're adding our appsettings JSON file.
*/
builder.AddJsonFile("appsettings.json");

/*
* Add the secrets manager
*/
builder.AddSecretsManager(configurator: op =>
{
/*
* Configure the secrets manager to read options
* from a certain config section
*/
op.ReadFromConfigSection("MySecretsManagerConfig");

/*
* Can still use the other options here
*/
op.KeyGenerator = (entry, key) => key.ToUpper();
});
}
}
}
23 changes: 23 additions & 0 deletions samples/Sample7/Sample7.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Kralizek.Extensions.Configuration.AWSSecretsManager\Kralizek.Extensions.Configuration.AWSSecretsManager.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions samples/Sample7/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"AWS": {
"Profile": "MyGeneralProfile",
"Region": "eu-west-2",
},
"MySecretsManagerConfig": {
"Profile": "MySecretsProfile",
"Region": "eu-west-1",
"ProfilesLocation": "C:\\Users\\MyUser\\.aws\\",
"PollingIntervalInSeconds": 60,
"AcceptedSecretArns": [
"arn:example:01-abcxyz",
"arn:example:02",
"unique-secret-name"
],
"ListSecretsFilters": [
{
"Key": "Name",
"Values": [ "Value1", "Value2" ]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Kralizek.Extensions.Configuration.Internal
{
/// <summary>
/// An object intended to bind an <see cref="IConfigurationSection"/> to.
/// </summary>
internal class AwsConfigSection
{
public const string DefaultConfigSectionName = "AWS";

/// <summary>
/// The string representation of an AWS Region.
/// </summary>
public string Region { get; set; }

/// <summary>
/// The name of the credentials profile to be used by the Secrets Manager client.
/// </summary>
public string Profile { get; set; }

/// <summary>
/// The location of the file containing the credentials profiles.
/// </summary>
public string ProfilesLocation { get; set; }
}
Copy link

@savornicesei savornicesei Nov 7, 2022

Choose a reason for hiding this comment

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

I've been thinking if it's better for the extension to handle everything or if it is worth taking a dependency on AWSSDK.Extensions.NETCore.Setup .

Unfortunately AWSOptions? options = settings.GetAWSOptions("AWS:SecretsManager"); from the mentioned AWS package does not initialize AWSCredentials for some reason.
To overcome this I added a new method to IConfiguration : GetAWSOptionsWithCredentials that also sets the options.Credentials.

Using AWSSDK.Extensions.NETCore.Setup will allow smooth integration with localstack through localstack-dotnet-client

Copy link
Owner

Choose a reason for hiding this comment

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

I'd like to keep this library as supple and lean as possible.

Choose a reason for hiding this comment

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

Yeah, makes sense

}
Loading