├── .gitignore
├── Configuration.Provider.Docker.Secrets.Tests
├── Configuration.Provider.Docker.Secrets.Tests.csproj
├── DockerSecretsConfigurationProviderTests.cs
└── DockerSecretsConfigurationSourceTests.cs
├── Configuration.Provider.Docker.Secrets.sln
├── Configuration.Provider.Docker.Secrets
├── AssemblySettings.cs
├── Configuration.Provider.Docker.Secrets.csproj
├── DockerSecretsConfigurationExtension.cs
├── DockerSecretsConfigurationProvider.cs
└── DockerSecretsConfigurationsSource.cs
├── License.md
└── Readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | /packages/
4 | .DS_Store
5 | .idea/
6 |
7 | # User-specific files
8 | *.user
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets.Tests/Configuration.Provider.Docker.Secrets.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets.Tests/DockerSecretsConfigurationProviderTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO.Abstractions.TestingHelpers;
4 | using FluentAssertions;
5 | using Mcrio.Configuration.Provider.Docker.Secrets;
6 | using Xunit;
7 |
8 | namespace Configuration.Provider.Docker.Secrets.Tests
9 | {
10 | public class DockerSecretsConfigurationProviderTests
11 | {
12 | [Fact]
13 | public void Secrets_directory_path_must_not_be_null()
14 | {
15 | Assert.Throws(() => new DockerSecretsConfigurationProvider(
16 | null,
17 | "__",
18 | new List()
19 | ));
20 | }
21 |
22 | [Fact]
23 | public void Colon_placeholder_must_not_be_null()
24 | {
25 | Assert.Throws(() => new DockerSecretsConfigurationProvider(
26 | "/run/secrets",
27 | null,
28 | new List()
29 | ));
30 | }
31 |
32 | [Fact]
33 | public void Load_secrets_from_file_and_replace_colon_placeholder_with_colon()
34 | {
35 | var fileSystemMock = new MockFileSystem();
36 | var secretsProvider = new DockerSecretsConfigurationProvider(
37 | "/run/secrets",
38 | "__",
39 | new List(),
40 | fileSystemMock
41 | );
42 |
43 | fileSystemMock.AddFile("/run/secrets/secret_one", new MockFileData("secret one content"));
44 | fileSystemMock.AddFile("/run/secrets/two", new MockFileData("two content"));
45 | fileSystemMock.AddFile("/run/secrets/foo__bar__baz", new MockFileData("foo bar baz content"));
46 | fileSystemMock.AddFile("/run/secrets/bar__foo", new MockFileData("bar foo content"));
47 |
48 | secretsProvider.Load();
49 |
50 | secretsProvider.TryGet("secret_one", out string secretOneValue).Should().BeTrue();
51 | secretOneValue.Should().BeEquivalentTo("secret one content");
52 |
53 | secretsProvider.TryGet("two", out string twoValue).Should().BeTrue();
54 | twoValue.Should().BeEquivalentTo("two content");
55 |
56 | secretsProvider.TryGet("foo:bar:baz", out string fooBarBazValue).Should().BeTrue();
57 | fooBarBazValue.Should().BeEquivalentTo("foo bar baz content");
58 | secretsProvider.TryGet("foo__bar__baz", out string _).Should().BeFalse("__ was replaced with :");
59 |
60 | secretsProvider.TryGet("bar:foo", out string barFooValue).Should().BeTrue();
61 | barFooValue.Should().BeEquivalentTo("bar foo content");
62 | secretsProvider.TryGet("bar__foo", out string _).Should().BeFalse("__ was replaced with :");
63 | }
64 |
65 | [Fact]
66 | public void Load_secrets_from_which_start_with_predefined_prefix()
67 | {
68 | var fileSystemMock = new MockFileSystem();
69 | var secretsProvider = new DockerSecretsConfigurationProvider(
70 | "/run/secrets",
71 | "__",
72 | new List
73 | {
74 | "foo__",
75 | "Bar__Baz"
76 | },
77 | fileSystemMock
78 | );
79 |
80 | fileSystemMock.AddFile("/run/secrets/secret_one", new MockFileData("secret one content"));
81 | fileSystemMock.AddFile("/run/secrets/two", new MockFileData("two content"));
82 | fileSystemMock.AddFile("/run/secrets/foo__bar__baz", new MockFileData("foo bar baz content"));
83 | fileSystemMock.AddFile("/run/secrets/bar__foo", new MockFileData("bar foo content"));
84 | fileSystemMock.AddFile("/run/secrets/baz__foo__bar", new MockFileData("baz foo bar content"));
85 | fileSystemMock.AddFile("/run/secrets/Bar__Baz__Secret_One", new MockFileData("Bar Baz Secret One content"));
86 |
87 | secretsProvider.Load();
88 |
89 | secretsProvider.TryGet("secret_one", out string secretOneValue).Should()
90 | .BeFalse("does not start with prefix");
91 | secretOneValue.Should().BeNull();
92 |
93 | secretsProvider.TryGet("two", out string twoValue).Should().BeFalse("does not start with prefix");
94 | twoValue.Should().BeNull();
95 |
96 | secretsProvider.TryGet("foo:bar:baz", out string fooBarBazValue).Should().BeTrue();
97 | fooBarBazValue.Should().BeEquivalentTo("foo bar baz content");
98 |
99 | secretsProvider.TryGet("bar:foo", out string barFooValue).Should().BeFalse("does not start with prefix");
100 | barFooValue.Should().BeNull();
101 | secretsProvider.TryGet("bar__foo", out string _).Should().BeFalse("does not start with prefix");
102 |
103 | secretsProvider.TryGet("baz:foo:bar", out string bazFooBarValue).Should()
104 | .BeFalse("does not start with prefix");
105 | bazFooBarValue.Should().BeNull();
106 | secretsProvider.TryGet("baz__foo__bar", out string _).Should().BeFalse("does not start with prefix");
107 |
108 | secretsProvider.TryGet("Bar:Baz:Secret_One", out string barBazSecretOne).Should().BeTrue();
109 | barBazSecretOne.Should().BeEquivalentTo("Bar Baz Secret One content");
110 | secretsProvider.TryGet("Bar__Baz__Secret_One", out string _).Should().BeFalse();
111 | }
112 |
113 | [Fact]
114 | public void Configuration_keys_should_be_case_insensitive()
115 | {
116 | var fileSystemMock = new MockFileSystem();
117 | var secretsProvider = new DockerSecretsConfigurationProvider(
118 | "/run/secrets",
119 | "__",
120 | new List
121 | {
122 | "foo__",
123 | },
124 | fileSystemMock
125 | );
126 |
127 | fileSystemMock.AddFile("/run/secrets/Foo__Secret_One", new MockFileData("secret one content"));
128 | fileSystemMock.AddFile("/run/secrets/foo__secret_two", new MockFileData("secret two content"));
129 |
130 | secretsProvider.Load();
131 |
132 | secretsProvider.TryGet("Foo:Secret_One", out string secretOne).Should()
133 | .BeTrue("prefix matches as casing is ignored");
134 | secretOne.Should().BeEquivalentTo("secret one content");
135 | secretsProvider.TryGet("Foo__Secret_One", out string _).Should().BeFalse();
136 |
137 | secretsProvider.TryGet("foo:secret_two", out string secretTwo).Should().BeTrue("prefix matches");
138 | secretTwo.Should().BeEquivalentTo("secret two content");
139 | secretsProvider.TryGet("foo__secret_two", out string _).Should().BeFalse();
140 | }
141 |
142 | [Fact]
143 | public void Return_no_configuration_if_secrets_folder_path_does_not_exist()
144 | {
145 | var fileSystemMock = new MockFileSystem();
146 | var secretsProvider = new DockerSecretsConfigurationProvider(
147 | "/run/secrets_two",
148 | "__",
149 | new List(),
150 | fileSystemMock
151 | );
152 |
153 | fileSystemMock.AddFile("/run/secrets/secret_one", new MockFileData("secret one content"));
154 |
155 | secretsProvider.Load();
156 |
157 | secretsProvider.TryGet("secret_one", out _).Should()
158 | .BeFalse("specified folder path differs from path where the secret is stored");
159 | }
160 |
161 | [Fact]
162 | public void Return_no_configuration_if_secret_file_does_not_exist()
163 | {
164 | var fileSystemMock = new MockFileSystem();
165 | var secretsProvider = new DockerSecretsConfigurationProvider(
166 | "/run/secrets",
167 | "__",
168 | new List(),
169 | fileSystemMock
170 | );
171 |
172 | secretsProvider.Load();
173 |
174 | secretsProvider.TryGet("secret_one", out _).Should()
175 | .BeFalse("/run/secrets/secret_one file does not exist");
176 | }
177 | }
178 | }
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets.Tests/DockerSecretsConfigurationSourceTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Xunit;
4 | using FluentAssertions;
5 | using Mcrio.Configuration.Provider.Docker.Secrets;
6 | using Microsoft.Extensions.Configuration;
7 | using Moq;
8 |
9 | namespace Configuration.Provider.Docker.Secrets.Tests
10 | {
11 | public class DockerSecretsConfigurationSourceTests
12 | {
13 | [Fact]
14 | public void Should_build_docker_secrets_provider()
15 | {
16 | var source = new DockerSecretsConfigurationsSource(
17 | "/run/secrets",
18 | "__",
19 | new List()
20 | );
21 | IConfigurationProvider provider = source.Build(new Mock().Object);
22 | provider.Should().BeOfType();
23 | }
24 |
25 | [Fact]
26 | public void Secrets_directory_path_should_not_be_null()
27 | {
28 | Assert.Throws(() => new DockerSecretsConfigurationsSource(
29 | null,
30 | "__",
31 | new List()
32 | ));
33 | }
34 |
35 | [Fact]
36 | public void Colon_plaecholder_path_should_not_be_null()
37 | {
38 | Assert.Throws(() => new DockerSecretsConfigurationsSource(
39 | "/run/secrets",
40 | null,
41 | new List()
42 | ));
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configuration.Provider.Docker.Secrets", "Configuration.Provider.Docker.Secrets\Configuration.Provider.Docker.Secrets.csproj", "{81D73F2D-049B-4199-BE90-0265953E58AE}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configuration.Provider.Docker.Secrets.Tests", "Configuration.Provider.Docker.Secrets.Tests\Configuration.Provider.Docker.Secrets.Tests.csproj", "{F2B619B9-F699-4E70-B34D-EAEE7D120A14}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {81D73F2D-049B-4199-BE90-0265953E58AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {81D73F2D-049B-4199-BE90-0265953E58AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {81D73F2D-049B-4199-BE90-0265953E58AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {81D73F2D-049B-4199-BE90-0265953E58AE}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {F2B619B9-F699-4E70-B34D-EAEE7D120A14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {F2B619B9-F699-4E70-B34D-EAEE7D120A14}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {F2B619B9-F699-4E70-B34D-EAEE7D120A14}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {F2B619B9-F699-4E70-B34D-EAEE7D120A14}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets/AssemblySettings.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | // Allow the tests project to access internal classes for unit tests
4 | [assembly: InternalsVisibleTo("Configuration.Provider.Docker.Secrets.Tests")]
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets/Configuration.Provider.Docker.Secrets.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | Mcrio.Configuration.Provider.Docker.Secrets
6 | Mcrio.Configuration.Provider.Docker.Secrets
7 | 1.0.1
8 | .NET Core configuration provider for Docker Secrets.
9 | Nikola Josipovic
10 | https://github.com/mcrio
11 | Mcrio.Configuration.Provider.Docker.Secrets
12 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
13 | https://github.com/mcrio/Configuration.Provider.Docker.Secrets
14 | git
15 | https://github.com/mcrio/Configuration.Provider.Docker.Secrets
16 | .net;dotnet;core;configuration;docker;secrets
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets/DockerSecretsConfigurationExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.Extensions.Configuration;
5 |
6 | namespace Mcrio.Configuration.Provider.Docker.Secrets
7 | {
8 | ///
9 | /// Provides ability to read configuration parameters from docker secrets files.
10 | ///
11 | public static class DockerSecretsConfigurationExtension
12 | {
13 | private const string DefaultSecretsDirectoryPath = "/run/secrets";
14 | private const string DefaultColonPlaceholder = "__";
15 | private const char PrefixesEnvironmentVariableDelimiter = ',';
16 |
17 | ///
18 | /// Read configuration from mounted docker secrets files
19 | ///
20 | /// Configuration builder
21 | /// Absolute path to the folder inside the container that holds the mounted Docker secret files.
22 | /// Provided placeholder value will be replaced with `:` within the secret filename.
23 | /// If not null and not empty reads only secret files that start with any of the provided prefixes.
24 | /// Configuration builder
25 | public static IConfigurationBuilder AddDockerSecrets(
26 | this IConfigurationBuilder configurationBuilder,
27 | string secretsDirectoryPath = DefaultSecretsDirectoryPath,
28 | string colonPlaceholder = DefaultColonPlaceholder,
29 | ICollection allowedPrefixes = null)
30 | {
31 | return configurationBuilder.Add(new DockerSecretsConfigurationsSource(
32 | secretsDirectoryPath,
33 | colonPlaceholder,
34 | allowedPrefixes
35 | ));
36 | }
37 |
38 | ///
39 | /// Read configuration from mounted docker secrets files
40 | ///
41 | /// Configuration builder
42 | /// Name of the environment variable that holds comma separated
43 | /// allowed prefixes. If prefixes are defined then processed are only secrets which file names start with any of the provided
44 | /// prefixes.
45 | /// Path to the folder what holds the mounted Docker secret files.
46 | /// Provided placeholder value will be replaced with `:` within the secret filename.
47 | /// Configuration builder
48 | public static IConfigurationBuilder AddDockerSecrets(
49 | this IConfigurationBuilder configurationBuilder,
50 | string allowedPrefixesEnvVariableName,
51 | string secretsDirectoryPath = DefaultSecretsDirectoryPath,
52 | string colonPlaceholder = DefaultColonPlaceholder
53 | )
54 | {
55 | if (string.IsNullOrWhiteSpace(allowedPrefixesEnvVariableName))
56 | {
57 | throw new ArgumentException(
58 | $"{nameof(allowedPrefixesEnvVariableName)} must not be NULL or empty."
59 | );
60 | }
61 |
62 | string allowedPrefixesCommaDelimited = Environment.GetEnvironmentVariable(allowedPrefixesEnvVariableName);
63 | ICollection allowedDockerPrefixes = string.IsNullOrWhiteSpace(allowedPrefixesCommaDelimited)
64 | ? null
65 | : allowedPrefixesCommaDelimited
66 | .Split(PrefixesEnvironmentVariableDelimiter)
67 | .Select(prefix => prefix.Trim())
68 | .Where(prefix => !string.IsNullOrWhiteSpace(prefix))
69 | .ToList();
70 |
71 | return configurationBuilder.AddDockerSecrets(secretsDirectoryPath, colonPlaceholder, allowedDockerPrefixes);
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets/DockerSecretsConfigurationProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.IO.Abstractions;
5 | using System.Linq;
6 | using Microsoft.Extensions.Configuration;
7 |
8 | namespace Mcrio.Configuration.Provider.Docker.Secrets
9 | {
10 | internal class DockerSecretsConfigurationProvider : ConfigurationProvider
11 | {
12 | private readonly string _secretsDirectoryPath;
13 | private readonly string _colonPlaceholder;
14 | private readonly ICollection _allowedPrefixes;
15 | private readonly IFileSystem _fileSystem;
16 |
17 | internal DockerSecretsConfigurationProvider(
18 | string secretsDirectoryPath,
19 | string colonPlaceholder,
20 | ICollection allowedPrefixes
21 | )
22 | : this(secretsDirectoryPath, colonPlaceholder, allowedPrefixes, new FileSystem())
23 | {
24 | }
25 |
26 | internal DockerSecretsConfigurationProvider(
27 | string secretsDirectoryPath,
28 | string colonPlaceholder,
29 | ICollection allowedPrefixes,
30 | IFileSystem fileSystem)
31 | {
32 | _secretsDirectoryPath = secretsDirectoryPath
33 | ?? throw new ArgumentNullException(nameof(secretsDirectoryPath));
34 | _colonPlaceholder = colonPlaceholder ?? throw new ArgumentNullException(nameof(colonPlaceholder));
35 | _allowedPrefixes = allowedPrefixes;
36 | _fileSystem = fileSystem;
37 | }
38 |
39 | public override void Load()
40 | {
41 | if (!_fileSystem.Directory.Exists(_secretsDirectoryPath))
42 | {
43 | return;
44 | }
45 |
46 | foreach (string secretFilePath in _fileSystem.Directory.EnumerateFiles(_secretsDirectoryPath))
47 | {
48 | ProcessFile(secretFilePath);
49 | }
50 | }
51 |
52 | private void ProcessFile(string secretFilePath)
53 | {
54 | if (string.IsNullOrWhiteSpace(secretFilePath) || !_fileSystem.File.Exists(secretFilePath))
55 | {
56 | return;
57 | }
58 |
59 | string secretFileName = _fileSystem.Path.GetFileName(secretFilePath);
60 | if (string.IsNullOrWhiteSpace(secretFileName))
61 | {
62 | return;
63 | }
64 |
65 | if (_allowedPrefixes != null && _allowedPrefixes.Count > 0)
66 | {
67 | if (!_allowedPrefixes.Any(
68 | prefix => secretFileName.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)
69 | ))
70 | {
71 | return;
72 | }
73 | }
74 |
75 | using (var reader = new StreamReader(_fileSystem.File.OpenRead(secretFilePath)))
76 | {
77 | string secretValue = reader.ReadToEnd();
78 | if (secretValue.EndsWith(Environment.NewLine))
79 | {
80 | secretValue = secretValue.Substring(0, secretValue.Length - 1);
81 | }
82 |
83 | string secretKey = secretFileName.Replace(
84 | _colonPlaceholder,
85 | ":"
86 | );
87 | Data.Add(secretKey, secretValue);
88 | }
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/Configuration.Provider.Docker.Secrets/DockerSecretsConfigurationsSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Microsoft.Extensions.Configuration;
4 |
5 | namespace Mcrio.Configuration.Provider.Docker.Secrets
6 | {
7 | internal class DockerSecretsConfigurationsSource : IConfigurationSource
8 | {
9 | private readonly string _secretsDirectoryPath;
10 | private readonly string _colonPlaceholder;
11 | private readonly ICollection _allowedPrefixes;
12 |
13 | internal DockerSecretsConfigurationsSource(
14 | string secretsDirectoryPath,
15 | string colonPlaceholder,
16 | ICollection allowedPrefixes = null)
17 | {
18 | _secretsDirectoryPath =
19 | secretsDirectoryPath ?? throw new ArgumentNullException(nameof(secretsDirectoryPath));
20 | _colonPlaceholder = colonPlaceholder ?? throw new ArgumentNullException(nameof(colonPlaceholder));
21 | _allowedPrefixes = allowedPrefixes;
22 | }
23 |
24 | public IConfigurationProvider Build(IConfigurationBuilder builder)
25 | {
26 | return new DockerSecretsConfigurationProvider(
27 | _secretsDirectoryPath,
28 | _colonPlaceholder,
29 | _allowedPrefixes
30 | );
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/License.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 https://github.com/mcrio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # .NET Core Configuration provider for Docker Secrets
2 |
3 | > Ability to map docker secrets files to .net core configuration.
4 |
5 |
6 | [](https://dev.azure.com/midnight-creative/Configuration.Provider.Docker.Secrets/_apis/build/status/Build?branchName=master)
7 | 
8 |
9 | This package allows reading docker secrets files and pull them into the .net core configuration.
10 | Docker by default mounts secrets as files at the `/run/secrets` directory. The secrets file names
11 | are used to identify the configuration targets.
12 |
13 | ### About Docker Secrets
14 | Docker secrets are part of the Docker swarm services. They are used to manage sensitive data which
15 | a container needs at runtime but which should not be stored in the container image or source control.
16 | Read more about docker secrets on the [official docker documentation pages](https://docs.docker.com/engine/swarm/secrets/).
17 |
18 | ## Getting Started
19 |
20 | Using the NuGet package manager install the [Mcrio.Configuration.Provider.Docker.Secrets](https://www.nuget.org/packages/Mcrio.Configuration.Provider.Docker.Secrets/)
21 | package, or add the following line to the `.csproj` file:
22 |
23 | ```xml
24 |
25 |
26 | 1.0.0
27 |
28 |
29 | ```
30 | **Note:** Replace version value with the latest version available.
31 |
32 | ## Usage
33 |
34 | By default all files within the directory `/run/secrets` are scanned and processed as configuration.
35 | .NET Core configuration uses `:` as the section delimiter.
36 | As `:` cannot be used in file names, use `__` in place where `:` is needed.
37 |
38 | `AddDockerSecrets()` allows overriding of the default values
39 | for the secrets directory path and the colon placeholder.
40 |
41 | Often we want to process just specific secrets files. By setting
42 | allowed prefixes we can narrow down which files will be processed.
43 |
44 | #### Simple usage
45 | ```cs
46 | var configuration = new ConfigurationBuilder()
47 | .AddDockerSecrets()
48 | .Build();
49 | var secretValue = configuration["mysecret"];
50 | ```
51 |
52 | #### ASP.NET Core
53 | ```cs
54 | // Program.cs
55 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
56 | WebHost.CreateDefaultBuilder(args)
57 | .ConfigureAppConfiguration(configBuilder =>
58 | {
59 | configBuilder.AddDockerSecrets();
60 |
61 | // allow command line arguments to override docker secrets
62 | if (args != null)
63 | {
64 | configBuilder.AddCommandLine(args);
65 | }
66 | })
67 | .UseStartup();
68 | ```
69 |
70 | #### Only process files that start with a predefined prefix
71 |
72 | ```cs
73 | configBuilder.AddDockerSecrets(
74 | allowedPrefixes: new List
75 | {
76 | "ConfigSection1__",
77 | "Foo__Bar__Baz"
78 | }
79 | );
80 | ```
81 |
82 | #### Specify environment variable name that holds comma delimited list of allowed prefixes
83 |
84 | ```bash
85 | setenv MY_SECRETS_PREFIXES "ConfigSection1__,Foo__Bar__Baz"
86 | ```
87 | ```cs
88 | configBuilder.AddDockerSecrets("MY_SECRETS_PREFIXES");
89 | ```
90 |
91 |
92 | #### Docker compose example
93 |
94 | ```yaml
95 | # docker compose compatible file
96 | services:
97 | myservice:
98 | environment:
99 | - MY_SECRETS_PREFIXES=ConfigSection1__,Foo__Bar__Baz
100 | secrets:
101 | - source: myservice_foobarbaz_dbpass
102 | target: Foo__Bar__Baz__DbPassword
103 |
104 | secrets:
105 | myservice_foobarbaz_dbpass:
106 | external: true
107 | name: myservice_foobarbaz_dbpass_2019_12_30_1
108 | ```
109 | ```cs
110 | // Program.cs
111 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
112 | WebHost.CreateDefaultBuilder(args)
113 | .ConfigureAppConfiguration(configBuilder =>
114 | {
115 | configBuilder.AddDockerSecrets(
116 | allowedPrefixesEnvVariableName: "MY_SECRETS_PREFIXES"
117 | );
118 |
119 | // allow command line arguments to override docker secrets
120 | if (args != null)
121 | {
122 | configBuilder.AddCommandLine(args);
123 | }
124 | })
125 | .UseStartup();
126 | ```
127 |
128 | ## Release History
129 |
130 | - **1.0.1**
131 | - Stable version that reads secret values from mounted files
132 | and pulls those into the configuration. Optionally
133 | filters the files to process by defined allowed prefixes.
134 |
135 | ## Meta
136 |
137 | Nikola Josipovic
138 |
139 | This project is licensed under the MIT License. See [License.md](License.md) for more information.
140 |
141 | ## Do you like this library?
142 |
143 |
addr1q87dhpq4wkm5gucymxkwcatu2et5enl9z8dal4c0fj98fxznraxyxtx5lf597gunnxn3tewwr6x2y588ttdkdlgaz79spp3avz
144 |
145 |
0xae0B28c1fCb707e1908706aAd65156b61aC6Ff0A
146 |
147 |
bc1q3s8qjx59f4wu7tvz7qj9qx8w6ktcje5ktseq68
148 |
149 |
https://palebluedotpool.org
150 |
--------------------------------------------------------------------------------